Skip to main content

multi_index_container/
lib.rs

1mod combined_getters;
2
3#[doc(hidden)]
4pub mod __private {
5    pub use pastey::paste;
6}
7
8#[derive(thiserror::Error, Debug)]
9#[error("Unique contraint violation on {field} for value {value:?}")]
10pub struct UniqueContraintViolation<T> {
11    pub field: &'static str,
12    pub value: T,
13}
14
15/// Macro to define a multi-index map with unique and non-unique indexes
16#[macro_export]
17macro_rules! multi_index_container {
18    (
19        $(#[$meta:meta])*
20        $vis:vis $map_name:ident<$value_type:ty> {
21            $(unique $unique_name:ident: $unique_key_type:ty => |$unique_param:ident| $unique_expr:expr,)*
22            $(non_unique $non_unique_name:ident: $non_unique_key_type:ty => |$non_unique_param:ident| $non_unique_expr:expr,)*
23            $(unique_ordered $unique_ordered_name:ident: $unique_ordered_key_type:ty => |$unique_ordered_param:ident| $unique_ordered_expr:expr,)*
24            $(non_unique_ordered $non_unique_ordered_name:ident: $non_unique_ordered_key_type:ty => |$non_unique_ordered_param:ident| $non_unique_ordered_expr:expr,)*
25        }
26    ) => {
27        use multi_index_container::__private::paste;
28
29        paste! {
30            /// A typed index into the underlying storage of [`$map_name`].
31            ///
32            /// Wraps a `usize` to provide type safety, preventing accidental mix-ups
33            /// between indices belonging to different maps.
34            ///
35            /// Derived traits:
36            /// - [`Clone`], [`Copy`] — cheap to duplicate; pass by value freely.
37            /// - [`PartialEq`], [`Eq`], [`Hash`] — usable as a map key or in sets.
38            /// - [`Default`] — initialises to index `0`.
39            #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
40            $vis struct [<$map_name StorageIndex>] (usize);
41
42            impl [<$map_name StorageIndex>] {
43                /// Returns the immediately following index.
44                ///
45                /// Useful when advancing through storage slots sequentially,
46                /// for example when inserting a new entry at the next available position.
47                ///
48                /// # Panics
49                /// Panics in debug mode if the inner `usize` overflows. In release mode
50                /// the value wraps silently.
51                pub fn next(&self) -> Self {
52                    Self ( self.0 + 1 )
53                }
54            }
55        }
56
57        $(#[$meta])*
58        #[doc = concat!("A map for storing `", stringify!($value_type), "` indexed by `", stringify!($storage_key_type), "`.")]
59        $(
60            #[doc = concat!("- Unique index `", stringify!($unique_name), "`: `", stringify!($unique_key_type), "`")]
61        )*
62        $(
63            #[doc = concat!("- Non-unique index `", stringify!($non_unique_name), "`: `", stringify!($non_unique_key_type), "`")]
64        )*
65        $(
66            #[doc = concat!("- Unique ordered index `", stringify!($unique_ordered_name), "`: `", stringify!($unique_ordered_key_type), "`")]
67        )*
68        $(
69            #[doc = concat!("- Non-unique ordered index `", stringify!($non_unique_ordered_name), "`: `", stringify!($non_unique_ordered_key_type), "`")]
70        )*
71        $vis struct $map_name {
72
73
74            #[doc = "Storage keys that have been freed and can be reused."]
75            freed_storage_keys: Vec< paste! { [<$map_name StorageIndex>] }>,
76
77            #[doc = "The next storage key to be assigned when no freed keys are available."]
78            next_storage_key: paste! { [<$map_name StorageIndex>] },
79            
80            #[doc = concat!("Primary storage mapping each index to its `", stringify!($value_type), "`.")]
81            storage: std::collections::HashMap<paste! { [<$map_name StorageIndex>] }, $value_type>,
82            
83            $(
84                #[doc = concat!("Unique index `", stringify!($unique_name), "` mapping `", stringify!($unique_key_type), "` to a single storage index.")]
85                $unique_name: std::collections::HashMap<$unique_key_type, paste! { [<$map_name StorageIndex>] }>,
86            )*
87            $(
88                #[doc = concat!("Non-unique index `", stringify!($non_unique_name), "` mapping `", stringify!($non_unique_key_type), "` to a set of storage indices.")]
89                $non_unique_name: std::collections::HashMap<$non_unique_key_type, std::collections::HashSet< paste! { [<$map_name StorageIndex>] } >>,
90            )*
91            $(
92                #[doc = concat!("Unique ordered index `", stringify!($unique_ordered_name), "` mapping `", stringify!($unique_ordered_key_type), "` to a single storage index.")]
93                $unique_ordered_name: std::collections::BTreeMap<$unique_ordered_key_type, paste! { [<$map_name StorageIndex>] } >,
94            )*
95            $(
96                #[doc = concat!("Non-unique ordered index `", stringify!($non_unique_ordered_name), "` mapping `", stringify!($non_unique_ordered_key_type), "` to a set of storage indices.")]
97                $non_unique_ordered_name: std::collections::BTreeMap<$non_unique_ordered_key_type, std::collections::HashSet< paste! { [<$map_name StorageIndex>] } >>,
98            )*
99        }
100
101        impl $map_name {
102            
103            #[doc = concat!("Initialise an empty ", stringify!($value_type))]
104            pub fn new() -> Self {
105                Self {
106                    freed_storage_keys: Vec::new(),
107                    next_storage_key: Default::default(),
108                    storage: std::collections::HashMap::new(),
109                    $(
110                        $unique_name: std::collections::HashMap::new(),
111                    )*
112                    $(
113                        $non_unique_name: std::collections::HashMap::new(),
114                    )*
115                    $(
116                        $unique_ordered_name: std::collections::BTreeMap::new(),
117                    )*
118                    $(
119                        $non_unique_ordered_name: std::collections::BTreeMap::new(),
120                    )*
121                }
122            }
123
124            #[doc = "Get a reference to a value in the store based on the storage index."]
125            pub fn get(&self, storage_key: &paste! { [<$map_name StorageIndex>] }) -> Option<&$value_type> {
126                self.storage.get(storage_key)
127            }
128
129            #[doc = concat!("Inserts a `", stringify!($value_type), "` and update all indexes with the new type.")]
130            pub fn insert(&mut self, value: $value_type) -> Result<(), multi_index_container::UniqueContraintViolation<$value_type>> {
131                // Check unique constraints
132                $(
133                    let $unique_param = &value;
134                    let unique_key = $unique_expr;
135                    if self.$unique_name.contains_key(&unique_key) {
136                        return Err(multi_index_container::UniqueContraintViolation { field: stringify!($unique_name), value } );
137                    }
138                )*
139                $(
140                    let $unique_ordered_param = &value;
141                    let unique_key = $unique_ordered_expr;
142                    if self.$unique_ordered_name.contains_key(&unique_key) {
143                        return Err(multi_index_container::UniqueContraintViolation { field: stringify!($unique_ordered_name), value } );
144                    }
145                )*
146
147                let storage_key = self.freed_storage_keys.pop().unwrap_or_else(
148                    || {
149                        let key = self.next_storage_key;
150                        self.next_storage_key = self.next_storage_key.next();
151                        key
152                    }
153                );
154
155                // Insert into storage
156                let storage_key_clone = storage_key;
157                self.storage.insert(storage_key, value);
158
159                // Update indexes
160                let stored_value = self.storage.get(&storage_key_clone).unwrap();
161
162                $(
163                    let $unique_param = stored_value;
164                    let unique_key = $unique_expr;
165                    self.$unique_name.insert(unique_key, storage_key_clone);
166                )*
167
168                $(
169                    let $non_unique_param = stored_value;
170                    let non_unique_key = $non_unique_expr;
171                    self.$non_unique_name
172                        .entry(non_unique_key)
173                        .or_default()
174                        .insert(storage_key_clone);
175                )*
176                $(
177                    let $unique_ordered_param = stored_value;
178                    let unique_ordered_key = $unique_ordered_expr;
179                    self.$unique_ordered_name.insert(unique_ordered_key, storage_key_clone);
180                )*
181                $(
182                    let $non_unique_ordered_param = stored_value;
183                    let non_unique_ordered_key = $non_unique_ordered_expr;
184                    self.$non_unique_ordered_name
185                        .entry(non_unique_ordered_key)
186                        .or_default()
187                        .insert(storage_key_clone);
188                )*
189
190                Ok(())
191            }
192
193            #[doc = concat!("Inserts a `", stringify!($value_type), "` overwriting any existing entries that conflict on unique indexes.")]
194            pub fn insert_or_overwrite(&mut self, value: $value_type) {
195                $(
196                    let $unique_param = &value;
197                    let unique_key = $unique_expr;
198                    if let Some(&conflicting_storage_key) = self.$unique_name.get(&unique_key) {
199                        self.remove(&conflicting_storage_key);
200                    }
201                )*
202                $(
203                    let $unique_ordered_param = &value;
204                    let unique_ordered_key = $unique_ordered_expr;
205                    if let Some(&conflicting_storage_key) = self.$unique_ordered_name.get(&unique_ordered_key) {
206                        self.remove(&conflicting_storage_key);
207                    }
208                )*
209
210                let storage_key = self.freed_storage_keys.pop().unwrap_or_else(
211                    || {
212                        let key = self.next_storage_key;
213                        self.next_storage_key = self.next_storage_key.next();
214                        key
215                    }
216                );
217
218                let storage_key_clone = storage_key;
219                self.storage.insert(storage_key, value);
220
221                let stored_value = self.storage.get(&storage_key_clone).unwrap();
222
223                $(
224                    let $unique_param = stored_value;
225                    let unique_key = $unique_expr;
226                    self.$unique_name.insert(unique_key, storage_key_clone);
227                )*
228
229                $(
230                    let $non_unique_param = stored_value;
231                    let non_unique_key = $non_unique_expr;
232                    self.$non_unique_name
233                        .entry(non_unique_key)
234                        .or_default()
235                        .insert(storage_key_clone);
236                )*
237                $(
238                    let $unique_ordered_param = stored_value;
239                    let unique_ordered_key = $unique_ordered_expr;
240                    self.$unique_ordered_name.insert(unique_ordered_key, storage_key_clone);
241                )*
242                $(
243                    let $non_unique_ordered_param = stored_value;
244                    let non_unique_ordered_key = $non_unique_ordered_expr;
245                    self.$non_unique_ordered_name
246                        .entry(non_unique_ordered_key)
247                        .or_default()
248                        .insert(storage_key_clone);
249                )*
250            }
251
252            $(
253                paste! {
254                    #[doc = concat!("Get a single value, if it exist, by indexing by the unique key `", stringify!($unique_name), "` .")]
255                    pub fn [<get_by_ $unique_name>](&self, $unique_name: &$unique_key_type) -> Option<&$value_type> {
256                        self.$unique_name
257                            .get($unique_name)
258                            .and_then(|storage_key| self.storage.get(storage_key))
259                    }
260
261                    #[doc = concat!("Get a mutable modifier for a value, if it exist, by indexing by the unique key `", stringify!($unique_name), "` .")]
262                    pub fn [<get_mut_by_ $unique_name>](&mut self, $unique_name: &$unique_key_type) -> Option<[<$map_name MutEntry>]> {
263                        let storage_key = self.$unique_name.get($unique_name)?;
264
265                        Some([<$map_name MutEntry>] {
266                            entry: *storage_key,
267                            hashmap: self
268                        })
269                    }
270                }
271            )*
272
273            $(
274                paste! {
275                    #[doc = concat!("Get a single value, if it exist, by indexing by the unique ordered key `", stringify!($unique_ordered_name), "` .")]
276                    pub fn [<get_by_ $unique_ordered_name>](&self, $unique_ordered_name: &$unique_ordered_key_type) -> Option<&$value_type> {
277                        self.$unique_ordered_name
278                            .get($unique_ordered_name)
279                            .and_then(|storage_key| self.storage.get(storage_key))
280                    }
281
282                    #[doc = concat!("Get a mutable modifier for a value, if it exist, by indexing by the unique ordered key `", stringify!($unique_name), "` .")]
283                    pub fn [<get_mut_by_ $unique_ordered_name>](&mut self, $unique_ordered_name: &$unique_ordered_key_type) -> Option<[<$map_name MutEntry>]> {
284                        let storage_key = self.$unique_ordered_name.get($unique_ordered_name)?;
285                        Some([<$map_name MutEntry>] {
286                            entry: *storage_key,
287                            hashmap: self
288                        })
289                    }
290
291                    $vis fn [<first_by_ $unique_ordered_name>](&self) -> Option<&$value_type> {
292                        self.$unique_ordered_name
293                            .first_key_value()
294                            .and_then(|(_, sk)| self.storage.get(sk))
295                    }
296
297                    $vis fn [<last_by_ $unique_ordered_name>](&self) -> Option<&$value_type> {
298                        self.$unique_ordered_name
299                            .last_key_value()
300                            .and_then(|(_, sk)| self.storage.get(sk))
301                    }
302
303                    $vis fn [<get_by_ $unique_ordered_name _range>]<R>(&self, range: R) -> impl Iterator<Item = &$value_type>
304                    where
305                        R: std::ops::RangeBounds<$unique_ordered_key_type>,
306                    {
307                        self.$unique_ordered_name
308                            .range(range)
309                            .filter_map(|(_, sk)| self.storage.get(sk))
310                    }
311                }
312            )*
313
314            $(
315                paste! {
316                    #[doc = concat!("Get the values by indexing by the non unique key `", stringify!($non_unique_name), "` .")]
317                    pub fn [<get_by_ $non_unique_name>]<'a>(&'a self, $non_unique_name: &$non_unique_key_type) -> impl Iterator<Item = &'a $value_type> {
318                        self.$non_unique_name
319                            .get($non_unique_name)
320                            .into_iter()
321                            .flat_map(|storage_keys| {
322                                storage_keys
323                                    .iter()
324                                    .filter_map(|sk| self.storage.get(sk))
325                            })
326                    }
327
328                    #[doc = concat!("Get a mutable modifier for a value, if it exist, by indexing by the non unique key `", stringify!($non_unique_name), "` .")]
329                    pub fn [<get_mut_by_ $non_unique_name>](&mut self, $non_unique_name: &$non_unique_key_type) -> [<$map_name MutEntries>] {
330                        let storage_keys = match self.$non_unique_name.get($non_unique_name) {
331                            Some(s) => s,
332                            None => return [<$map_name MutEntries>] {
333                                entries: vec![].into_iter(),
334                                hashmap: self,
335                            },
336                        };
337
338                        [<$map_name MutEntries>] {
339                            entries: storage_keys.clone().into_iter().collect::<Vec<_>>().into_iter(),
340                            hashmap: self,
341                        }
342                    }
343                }
344            )*
345
346            $(
347                paste! {
348                    #[doc = concat!("Get the values by indexing by the non unique ordered key `", stringify!($non_unique_ordered_name), "` .")]
349                    pub fn [<get_by_ $non_unique_ordered_name>]<'a>(&'a self, $non_unique_ordered_name: &$non_unique_ordered_key_type) -> impl Iterator<Item = &'a $value_type> {
350                        self.$non_unique_ordered_name
351                            .get($non_unique_ordered_name)
352                            .into_iter()
353                            .flat_map(|storage_keys| {
354                                storage_keys
355                                    .iter()
356                                    .filter_map(|sk| self.storage.get(sk))
357                            })
358                    }
359
360                    #[doc = concat!("Get a mutable modifier for a value, if it exist, by indexing by the non unique ordered key `", stringify!($non_unique_ordered_name), "` .")]
361                    pub fn [<get_mut_by_ $non_unique_ordered_name>](&mut self, $non_unique_ordered_name: &$non_unique_ordered_key_type) -> [<$map_name MutEntries>] {
362                        let storage_keys = match self.$non_unique_ordered_name.get($non_unique_ordered_name) {
363                            Some(s) => s,
364                            None => return [<$map_name MutEntries>] {
365                                entries: vec![].into_iter(),
366                                hashmap: self,
367                            },
368                        };
369
370                        [<$map_name MutEntries>] {
371                            entries: storage_keys.clone().into_iter().collect::<Vec<_>>().into_iter(),
372                            hashmap: self,
373                        }
374                    }
375
376                    $vis fn [<first_by_ $non_unique_ordered_name>](&self) -> impl Iterator<Item = &$value_type> {
377                        self.$non_unique_ordered_name
378                            .first_key_value()
379                            .into_iter()
380                            .flat_map(|(_, storage_keys)| {
381                                storage_keys
382                                    .iter()
383                                    .filter_map(|sk| self.storage.get(sk))
384                            })
385                    }
386
387                    $vis fn [<last_by_ $non_unique_ordered_name>](&self) -> impl Iterator<Item = &$value_type> {
388                        self.$non_unique_ordered_name
389                            .last_key_value()
390                            .into_iter()
391                            .flat_map(|(_, storage_keys)| {
392                                storage_keys
393                                    .iter()
394                                    .filter_map(|sk| self.storage.get(sk))
395                            })
396                    }
397
398                    $vis fn [<get_by_ $non_unique_ordered_name _range>]<R>(&self, range: R) -> impl Iterator<Item = &$value_type>
399                    where
400                        R: std::ops::RangeBounds<$non_unique_ordered_key_type>,
401                    {
402                        self.$non_unique_ordered_name
403                            .range(range)
404                            .flat_map(|(_, storage_keys)| {
405                                storage_keys
406                                    .iter()
407                                    .filter_map(|sk| self.storage.get(sk))
408                            })
409                    }
410                }
411            )*
412
413            $crate::__multimap_combined_getters!(@generate_combos
414                $vis $map_name<$value_type>,
415                all_fields: [
416                    $(($non_unique_name: $non_unique_key_type))*
417                    $(($non_unique_ordered_name: $non_unique_ordered_key_type))*
418                ],
419                selected: [],
420                remaining: [
421                    $($non_unique_name: $non_unique_key_type,)*
422                    $($non_unique_ordered_name: $non_unique_ordered_key_type,)*
423                ]
424            );
425
426            $crate::__multimap_combined_ordered_getters!(@generate_combos
427                $vis $map_name<$value_type>,
428                eq_fields: [
429                    $($non_unique_name: $non_unique_key_type,)*
430                    $($non_unique_ordered_name: $non_unique_ordered_key_type,)*
431                ],
432                ordered_fields: [
433                    $($non_unique_ordered_name: $non_unique_ordered_key_type,)*
434                ]
435            );
436
437            #[doc = concat!("Remove entry from store by unique key.")]
438            pub fn remove(&mut self, storage_key: &paste! { [<$map_name StorageIndex>] }) -> Option<$value_type> {
439                let value = self.storage.remove(storage_key)?;
440
441                // Remove from unique indexes
442                $(
443                    let $unique_param = &value;
444                    let unique_key = $unique_expr;
445                    self.$unique_name.remove(&unique_key);
446                )*
447
448                // Remove from non-unique indexes
449                $(
450                    let $non_unique_param = &value;
451                    let non_unique_key = $non_unique_expr;
452                    if let Some(keys) = self.$non_unique_name.get_mut(&non_unique_key) {
453                        keys.retain(|k| k != storage_key);
454                        if keys.is_empty() {
455                            self.$non_unique_name.remove(&non_unique_key);
456                        }
457                    }
458                )*
459
460                // Remove from unique ordered indexes
461                $(
462                    let $unique_ordered_param = &value;
463                    let unique_ordered_key = $unique_ordered_expr;
464                    self.$unique_ordered_name.remove(&unique_ordered_key);
465                )*
466                // Remove from non-unique ordered indexes
467                $(
468                    let $non_unique_ordered_param = &value;
469                    let non_unique_ordered_key = $non_unique_ordered_expr;
470                    if let Some(keys) = self.$non_unique_ordered_name.get_mut(&non_unique_ordered_key) {
471                        keys.remove(storage_key);
472                        if keys.is_empty() {
473                            self.$non_unique_ordered_name.remove(&non_unique_ordered_key);
474                        }
475                    }
476                )*
477
478                self.freed_storage_keys.push(*storage_key);
479
480                Some(value)
481            }
482            
483            #[doc = "Get the number of values in the store"]
484            #[inline]
485            pub fn len(&self) -> usize {
486                self.storage.len()
487            }
488            
489            #[doc = "Check if the map is empty"]
490            #[inline]
491             pub fn is_empty(&self) -> bool {
492                 self.storage.is_empty()
493            }
494            
495             #[doc = "Extend the map with multiple values, returning a vector of all the unique contraint errors."]
496             pub fn extend<I>(&mut self, iter: I) -> Vec<multi_index_container::UniqueContraintViolation<$value_type>>
497             where
498                 I: IntoIterator<Item = $value_type>,
499             {
500                 let mut errors = Vec::new();
501                 for value in iter {
502                     if let Err(e) = self.insert(value) {
503                         errors.push(e);
504                     }
505                 }
506                 errors
507             }
508            
509             #[doc = "Iterate over all the values in the map."]
510             pub fn values(&self) -> std::collections::hash_map::Values<'_, paste! { [<$map_name StorageIndex>] }, $value_type> {
511                 self.storage.values()
512             }
513        }
514
515        impl Default for $map_name {
516
517            #[inline]
518            fn default() -> Self {
519                Self::new()
520            }
521        }
522
523        paste! {
524            #[doc = concat!("An iterator likey type of mutable entry handles into [`", stringify!($map_name), "`], produced by a multi-key lookup.")]
525            #[doc = ""]
526            #[doc = "Holds exclusive mutable access to the map for its lifetime `'map`, ensuring"]
527            #[doc = "no other mutable borrows can exist while entries are being traversed or modified."]
528            #[doc = ""]
529            #[doc = "Obtained from methods that look up multiple keys at once (e.g. `get_many_mut`)."]
530            #[doc = concat!("Each item yielded is a [`", stringify!($map_name), "MutEntry`], which allows in-place mutation or removal of that individual entry.")]
531            #[doc = ""]
532            #[doc = "# Notes"]
533            #[doc = "- Entries are yielded in the same order as the keys passed to the originating lookup."]
534            #[doc = "- Indices that no longer exist in the map at iteration time are silently skipped"]
535            #[doc = "  by consuming methods such as `remove_all` and `collect_values`."]
536            #[doc = ""]
537            #[doc = "# Lifetimes"]
538            #[doc = concat!("- `'map` — ties this iterator to the mutable borrow of the underlying [`", stringify!($map_name), "`], preventing any other access to the map until the iterator is dropped.")]
539            $vis struct [<$map_name MutEntries>]<'map> {
540                entries: std::vec::IntoIter<[<$map_name StorageIndex>]>,
541                hashmap: &'map mut $map_name,
542            }
543
544            impl<'map> [<$map_name MutEntries>]<'map> {
545                /// Creates an iterator which uses a closure to determine if an element should be yielded.
546                ///
547                /// Given an element the closure must return true or false. The returned iterator will yield only the elements for which the closure returns true.
548                pub fn filter<F>(self, mut predicate: F) -> Self
549                where
550                    F: FnMut(&$value_type) -> bool,
551                {
552                    let filtered: Vec<_> = self
553                        .entries
554                        .filter(|index| {
555                            self.hashmap
556                                .storage
557                                .get(index)
558                                .map(|v| predicate(v))
559                                .unwrap_or(false)
560                        })
561                        .collect();
562
563                    Self {
564                        entries: filtered.into_iter(),
565                        hashmap: self.hashmap,
566                    }
567                }
568                
569                /// Get a value from the yielded results.
570                pub fn first(self) -> Option<[<$map_name MutEntry>]<'map>> {
571                    let hashmap = self.hashmap;
572                    self.entries
573                        .into_iter()
574                        .next()
575                        .map(|entry| [<$map_name MutEntry>] { entry, hashmap })
576                }
577                
578                /// Calls a closure on each element of an iterator.
579                pub fn for_each<F>(self, mut f: F)
580                where
581                    F: for<'entry> FnMut([<$map_name MutEntry>]<'entry>),
582                {
583                    let hashmap = self.hashmap;
584                    for entry in self.entries {
585                        f([<$map_name MutEntry>] { entry, hashmap });
586                    }
587                }
588                
589                /// Searches for an element of an iterator that satisfies a predicate.
590                pub fn find<F>(self, mut predicate: F) -> Option<[<$map_name MutEntry>]<'map>>
591                where
592                    F: FnMut(&$value_type) -> bool,
593                {
594                    let hashmap = self.hashmap;
595                    let found = self.entries
596                        .into_iter()
597                        .find(|index| {
598                            hashmap
599                                .storage
600                                .get(index)
601                                .map(|v| predicate(v))
602                                .unwrap_or(false)
603                        });
604
605                    found.map(|entry| [<$map_name MutEntry>] { entry, hashmap })
606                }
607                
608                /// Removes all entries in this multi-entry selection from the map, returning their values.
609                ///
610                /// # Returns
611                /// A `Vec` containing the removed values, in iteration order.
612                pub fn remove_all(self) -> Vec<$value_type> {
613                    let hashmap = self.hashmap;
614                    self.entries
615                        .into_iter()
616                        .filter_map(|entry| {
617                            hashmap
618                                .storage
619                                .get(&entry)
620                                .is_some()
621                                .then(|| [<$map_name MutEntry>] { entry, hashmap }.remove())
622                        })
623                        .collect()
624                }
625
626                /// Returns the last entry in this selection as a mutable entry handle, if any.
627                ///
628                /// # Returns
629                /// `Some(MutEntry)` for the last entry, or `None` if the selection is empty.
630                pub fn last(self) -> Option<[<$map_name MutEntry>]<'map>> {
631                    let hashmap = self.hashmap;
632                    self.entries
633                        .into_iter()
634                        .last()
635                        .map(|entry| [<$map_name MutEntry>] { entry, hashmap })
636                }
637
638                /// Returns the entry at position `n` in this selection as a mutable entry handle, if any.
639                ///
640                /// # Parameters
641                /// - `n`: Zero-based index into the selection.
642                ///
643                /// # Returns
644                /// `Some(MutEntry)` for the nth entry, or `None` if `n` is out of bounds.
645                pub fn nth(self, n: usize) -> Option<[<$map_name MutEntry>]<'map>> {
646                    let hashmap = self.hashmap;
647                    self.entries
648                        .into_iter()
649                        .nth(n)
650                        .map(|entry| [<$map_name MutEntry>] { entry, hashmap })
651                }
652
653                /// Returns the number of entries in this selection.
654                #[inline]
655                pub fn count(self) -> usize {
656                    self.entries.len()
657                }
658
659                /// Returns `true` if this selection contains no entries.
660                #[inline]
661                pub fn is_empty(self) -> bool {
662                    self.entries.len() == 0
663                }
664
665                /// Returns `true` if this selection contains at least one entry.
666                #[inline]
667                pub fn is_not_empty(self) -> bool {
668                    self.entries.len() != 0
669                }
670                /// Collects shared references to the values of all entries in this selection.
671                ///
672                /// Entries that no longer exist in the map are silently skipped.
673                ///
674                /// # Returns
675                /// A `Vec` of references to the values, in iteration order.
676                pub fn collect_values(self) -> Vec<&'map $value_type> {
677                    let hashmap = self.hashmap;
678                    self.entries
679                        .into_iter()
680                        .filter_map(|index| hashmap.storage.get(&index))
681                        .collect()
682                }
683            }
684        }
685
686        paste! {
687            $vis struct [<$map_name MutEntry>] <'map> {
688                entry: [<$map_name StorageIndex>],
689                hashmap: &'map mut $map_name,
690            }
691
692            impl<'map> [<$map_name MutEntry>]<'map> {
693
694                /// Remove the value from the hashmap
695                pub fn remove(&mut self) -> $value_type {
696                    self.hashmap.remove(&self.entry).expect("Expected the value to exist given it is guaranteed by the mutable pointer to the hashmap while this reference is initialised.")
697                }
698
699                pub fn get(&self) -> &$value_type {
700                    self.hashmap.get(&self.entry).expect("Expected the value to exist given it is guaranteed by the mutable pointer to the hashmap while this reference is initialised.")
701                }
702
703                #[doc = concat!("Modify a `", stringify!($value_type), "` such that indexes are kept up to date.")]
704                #[doc = "If a modified value would fail to be inserted, the original value remains in place while the new value gets returned as part of the error. This means it is cloned as part of this function. To avoid this clone you can use the modify_or_remove function"]
705                pub fn modify<F>(&mut self, f: F) -> Result<(), multi_index_container::UniqueContraintViolation<$value_type>>
706                where
707                    F: for<'entry> FnOnce(&'entry mut $value_type),
708                {
709                    let value = self.remove();
710                    let mut modifiable_value = value.clone();
711                    f(&mut modifiable_value);
712
713                    if let Err(error) = self.hashmap.insert(modifiable_value) {
714                        self.hashmap.insert(value).expect("Expected to be able to insert the value we just removed.");
715
716                        return Err(error)
717                    }
718
719                    Ok(())
720                }
721
722                #[doc = concat!("Modify a `", stringify!($value_type), "` such that indexes are kept up to date.")]
723                #[doc = "If a modified value would fail to be inserted, the original value is lost."]
724                pub fn modify_or_remove<F>(&mut self, f: F) -> Result<(), multi_index_container::UniqueContraintViolation<$value_type>>
725                where
726                    F: for<'entry> FnOnce(&'entry mut $value_type),
727                {
728                    let mut modifiable_value = self.remove();
729                    f(&mut modifiable_value);
730
731                    self.hashmap.insert(modifiable_value)
732                }
733            }
734        }
735    };
736}