1
#![cfg_attr(docsrs, feature(doc_cfg))]
2
#![doc = include_str!("../README.md")]
3
// @@ begin lint list maintained by maint/add_warning @@
4
#![allow(renamed_and_removed_lints)] // @@REMOVE_WHEN(ci_arti_stable)
5
#![allow(unknown_lints)] // @@REMOVE_WHEN(ci_arti_nightly)
6
#![warn(missing_docs)]
7
#![warn(noop_method_call)]
8
#![warn(unreachable_pub)]
9
#![warn(clippy::all)]
10
#![deny(clippy::await_holding_lock)]
11
#![deny(clippy::cargo_common_metadata)]
12
#![deny(clippy::cast_lossless)]
13
#![deny(clippy::checked_conversions)]
14
#![allow(clippy::cognitive_complexity)] // See arti#2556
15
#![deny(clippy::debug_assert_with_mut_call)]
16
#![deny(clippy::exhaustive_enums)]
17
#![deny(clippy::exhaustive_structs)]
18
#![deny(clippy::expl_impl_clone_on_copy)]
19
#![deny(clippy::fallible_impl_from)]
20
#![deny(clippy::implicit_clone)]
21
#![deny(clippy::large_stack_arrays)]
22
#![warn(clippy::manual_ok_or)]
23
#![deny(clippy::missing_docs_in_private_items)]
24
#![warn(clippy::needless_borrow)]
25
#![warn(clippy::needless_pass_by_value)]
26
#![warn(clippy::option_option)]
27
#![deny(clippy::print_stderr)]
28
#![deny(clippy::print_stdout)]
29
#![warn(clippy::rc_buffer)]
30
#![deny(clippy::ref_option_ref)]
31
#![warn(clippy::semicolon_if_nothing_returned)]
32
#![warn(clippy::trait_duplication_in_bounds)]
33
#![deny(clippy::unchecked_time_subtraction)]
34
#![deny(clippy::unnecessary_wraps)]
35
#![warn(clippy::unseparated_literal_suffix)]
36
#![deny(clippy::unwrap_used)]
37
#![deny(clippy::mod_module_files)]
38
#![allow(clippy::let_unit_value)] // This can reasonably be done for explicitness
39
#![allow(clippy::uninlined_format_args)]
40
#![allow(clippy::significant_drop_in_scrutinee)] // arti/-/merge_requests/588/#note_2812945
41
#![allow(clippy::result_large_err)] // temporary workaround for arti#587
42
#![allow(clippy::needless_raw_string_hashes)] // complained-about code is fine, often best
43
#![allow(clippy::needless_lifetimes)] // See arti#1765
44
#![allow(mismatched_lifetime_syntaxes)] // temporary workaround for arti#2060
45
#![allow(clippy::collapsible_if)] // See arti#2342
46
#![deny(clippy::unused_async)]
47
#![deny(clippy::string_slice)] // See arti#2571
48
#![allow(recursion_depth_exceeding_limit)] // arti#2715, rust/issues/159228
49
//! <!-- @@ end lint list maintained by maint/add_warning @@ -->
50

            
51
mod key_data;
52

            
53
pub use slotmap::{
54
    DefaultKey, Key, KeyData, SecondaryMap, SparseSecondaryMap, new_key_type, secondary,
55
};
56

            
57
use key_data::key_version_serde as key_version;
58

            
59
//use key_version::key_version_serde;
60

            
61
/// A single entry in one of our careful slotmaps.
62
///
63
/// An entry can either be `Present` (in which case we treat it normally),
64
/// or `Unusable`, in which case we
65
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
66
#[derive(Debug, Clone)]
67
enum Entry<V> {
68
    /// The entry is available.
69
    Present(V),
70
    /// The entry can no longer be used, removed, or set to anything else.
71
    ///
72
    /// It must not be removed from the slot map, since doing so would
73
    /// increase its slot's version number too high.
74
    Unusable,
75
}
76

            
77
impl<V> Entry<V> {
78
    /// Remove the value of `self` (if any), and make it unusable.
79
60
    fn take_and_mark_unusable(&mut self) -> Option<V> {
80
60
        match std::mem::replace(self, Entry::Unusable) {
81
24
            Entry::Present(v) => Some(v),
82
36
            Entry::Unusable => None,
83
        }
84
60
    }
85
    /// Return a reference to the value of `self`, if there is one.
86
438
    fn value(&self) -> Option<&V> {
87
438
        match self {
88
406
            Entry::Present(val) => Some(val),
89
32
            Entry::Unusable => None,
90
        }
91
438
    }
92
    /// Return a mutable reference to the value of `self``, if there is one.
93
36581680
    fn value_mut(&mut self) -> Option<&mut V> {
94
36581680
        match self {
95
36581676
            Entry::Present(val) => Some(val),
96
4
            Entry::Unusable => None,
97
        }
98
36581680
    }
99
    /// Consume this entry (which must be `Present`), and return its value.
100
    ///
101
    /// # Panics
102
    ///
103
    /// Panics if this entry is `Unusable`.
104
143254
    fn unwrap(self) -> V {
105
143254
        match self {
106
143254
            Entry::Present(val) => val,
107
            Entry::Unusable => panic!("Tried to unwrap an unusable slot."),
108
        }
109
143254
    }
110
}
111

            
112
/// Helper: Define a wrapper for a single SlotMap type.
113
///
114
/// This works for SlotMap, and DenseSlotMap.
115
///
116
/// (The alternative to using a macro here would be to define a new trait
117
/// implemented by all of the SlotMaps, and then to define our own SlotMap as a wrapper around an
118
/// instance of that trait.)
119
macro_rules! define_implementation {
120
        { $mapname:ident } => {paste::paste!{
121

            
122
        /// A variation of
123
        #[doc = concat!("[`slotmap::", stringify!($mapname), "`]")]
124
        /// that can never give the same key for multiple objects.
125
        ///
126
        /// Unlike a regular version of
127
        #[doc = concat!("`", stringify!($mapname), "`,")]
128
        /// this version will not allow a slot's version counter to roll over to
129
        /// 0 if it reaches 2^31.  Instead, it will mark the slot as unusable for future values.
130
        ///
131
        /// # Limitations
132
        ///
133
        /// The possibility of marking a slot as unusable
134
        /// makes it possible, given enough removals and re-insertions,
135
        /// for a slotmap to use an unbounded amount of memory, even if it is not storing much actual data.
136
        /// (From a DOS point of view: Given the ability to re-insert an entry ~2^31 times, an attacker can
137
        /// cause a slot-map to render approximately `4+sizeof(V)` bytes unusable.)
138
        ///
139
        /// This type does not include implementations for:
140
        ///   * `get_unchecked_mut()`
141
        ///   * `get_disjoint_unchecked_mut()`
142
        ///   * `IntoIterator`.
143
        ///   * `serde::{Serialize, Deserialize}`.
144
        ///
145
        /// # Risky business!
146
        ///
147
        /// This code relies upon stability of some undocumented properties of `slotmap` keys.
148
        /// In particular, it assumes:
149
        ///  * that the slotmap KeyData `serde` format is stable,
150
        ///  * that slot versions are represented as `u32`.
151
        ///  * that the least significant bit of a slot version is 1 if the slot is full,
152
        ///    and 0 if the slot is empty.
153
        ///  * that slot versions start at 0, and increase monotonically as the slot is
154
        ///    emptied and reused.
155
        ///
156
        /// Note that these assumptions are _probably_ okay: if `slotmap` were to change them,
157
        /// it would thereby create a breaking change in its serde version.
158
        //
159
        // Invariants:
160
        //
161
        // For every `(key,value)` that is present in `base`:
162
        //   - `key_okay(key)` is true.
163
        //   - if `value` is `Entry::Unusable`, then `key_version(key) == SATURATE_AT_VERSION`.
164
        //
165
        // `n_unusable` is the number of entries in `base` whose value is `Entry::Unusable`.
166
        //
167
        // To maintain these invariants:
168
        //   - Never remove a key with `key_version(key) == SATURATE_AT_VERSION`
169
        //   - Whenever setting a value to `Unusable`, increment `n_unusable`.
170
        #[derive(Clone, Debug)]
171
        pub struct $mapname<K: Key, V> {
172
            /// An underlying SlotMap, obeying the invariants above.
173
            base: slotmap::$mapname<K, Entry<V>>,
174
            /// The number of entries in this SlotMap that are filled with [`Entry::Unusable`] values.
175
            n_unusable: usize,
176
            /// A ZST, used to guarantee that we have spot-checked the behavior of the underlying
177
            /// SlotMap implementation.
178
            _valid: [<$mapname ValidationToken>],
179
        }
180

            
181
        impl<V> $mapname<DefaultKey, V> {
182
            /// Construct a new empty map, using a default key type.
183
            ///
184
            /// See
185
            #[doc = concat!("[`slotmap::", stringify!($mapname), "::new()`].")]
186
4
            pub fn new() -> Self {
187
4
                Self::with_key()
188
4
            }
189

            
190
            /// Construct a new empty map with a specified capacity, using a default key type.
191
            ///
192
            /// See
193
            #[doc = concat!("[`slotmap::", stringify!($mapname), "::with_capacity()`].")]
194
            /// ::with_capacity()`].
195
4
            pub fn with_capacity(capacity: usize) -> Self {
196
4
                Self::with_capacity_and_key(capacity)
197
4
            }
198
        }
199

            
200
        impl<K: Key, V> Default for $mapname<K, V> {
201
172050
            fn default() -> Self {
202
172050
                Self::with_key()
203
172050
            }
204
        }
205

            
206
        impl<K: Key, V> $mapname<K, V> {
207
            /// Construct a new empty map, using a specialized key type.
208
            ///
209
            /// See
210
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::with_key()`].")]
211
172766
            pub fn with_key() -> Self {
212
172766
                Self::with_capacity_and_key(0)
213
172766
            }
214

            
215
            /// Construct a new empty map with a specified capacity, using a specialized key type.
216
            ///
217
            /// See
218
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::with_capacity_and_key()`].")]
219
172770
            pub fn with_capacity_and_key(capacity: usize) -> Self {
220
172770
                Self {
221
172770
                    base: slotmap::$mapname::with_capacity_and_key(capacity),
222
172770
                    n_unusable: 0,
223
172770
                    _valid: [<validate_ $mapname:snake _behavior>](),
224
172770
                }
225
172770
            }
226

            
227
            /// Return the number of items in this map.
228
            ///
229
            /// See
230
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::len()`].")]
231
372
            pub fn len(&self) -> usize {
232
372
                self.base
233
372
                    .len()
234
372
                    .checked_sub(self.n_unusable)
235
372
                    .expect("logic error")
236
372
            }
237

            
238
            /// Return true if this map has no items.
239
            ///
240
            /// See
241
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::is_empty()`].")]
242
36
            pub fn is_empty(&self) -> bool {
243
36
                self.len() == 0
244
36
            }
245

            
246
            /// Return the total number of slots available for entries in this map.
247
            ///
248
            /// This number includes used slots, as well as empty slots that may become used.
249
            ///
250
            /// See
251
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::capacity()`],")]
252
            /// but note that a `slotmap-careful` implementation may _lose_ capacity over time,
253
            /// as slots are marked unusable.
254
12
            pub fn capacity(&self) -> usize {
255
12
                self.base
256
12
                    .capacity()
257
12
                    .checked_sub(self.n_unusable)
258
12
                    .expect("logic error")
259
12
            }
260

            
261
            /// Reserve space as needed.
262
            ///
263
            /// Allocates if needed, so that this map can hold `additional` new entries
264
            /// without having to resize.
265
            ///
266
            /// See
267
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::reserve()`].")]
268
4
            pub fn reserve(&mut self, additional: usize) {
269
                // Note that we don't need to check n_unusable here: the underlying
270
                // map type thinks that unusable entries are full, and so will allocate
271
                // correctly.
272
4
                self.base.reserve(additional);
273
4
            }
274

            
275
            /// Return true if the map contains an entry with a given key.
276
            ///
277
            /// See
278
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::contains_key()`].")]
279
40
            pub fn contains_key(&self, key: K) -> bool {
280
                // Calling self.get, not self.base.get, so it will be None if the
281
                // slot is unusable.
282
40
                self.get(key).is_some()
283
40
            }
284

            
285
            /// Insert a new value into the map, and return the key used for it.
286
            ///
287
            /// See
288
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::insert()`].")]
289
191220
            pub fn insert(&mut self, value: V) -> K {
290
191220
                let key = self.base.insert(Entry::Present(value));
291
191220
                debug_assert!(key_okay(key));
292
191220
                key
293
191220
            }
294

            
295
            /// Insert a new value into the map, constructing it using its own new key.
296
            ///
297
            /// This method is useful for the case where a value needs to refer to the
298
            /// key that will be assigned to it.
299
            ///
300
            /// See
301
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::insert_with_key()`].")]
302
4
            pub fn insert_with_key<F>(&mut self, f: F) -> K
303
4
            where
304
4
                F: FnOnce(K) -> V,
305
            {
306
4
                let key = self.base.insert_with_key(|k| Entry::Present(f(k)));
307
4
                debug_assert!(key_okay(key));
308
4
                key
309
4
            }
310

            
311
            /// As [`Self::insert_with_key`], but may return an `Err`.
312
            ///
313
            /// See
314
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::try_insert_with_key()`].")]
315
8
            pub fn try_insert_with_key<F, E>(&mut self, f: F) -> Result<K, E>
316
8
            where
317
8
                F: FnOnce(K) -> Result<V, E>,
318
            {
319
8
                let key = self
320
8
                    .base
321
8
                    .try_insert_with_key(|k| Ok(Entry::Present(f(k)?)))?;
322
4
                debug_assert!(key_okay(key));
323
4
                Ok(key)
324
8
            }
325

            
326
            /// Remove and return the element of this map with a given key.
327
            ///
328
            /// Return None if the key is not present in the map.
329
            ///
330
            /// See
331
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::remove()`].")]
332
143330
            pub fn remove(&mut self, key: K) -> Option<V> {
333
143330
                if key_version_is_maximal(key) {
334
                    // The key is as large as it is allowed to get,
335
                    // so we should not actually remove this Entry.
336
64
                    match self.base.get_mut(key) {
337
60
                        Some(slot) => {
338
                            // The entry is Present: extract its value and mark it unusable.
339
60
                            let rv = slot.take_and_mark_unusable();
340
60
                            if rv.is_some() {
341
24
                                self.n_unusable += 1;
342
36
                            }
343
60
                            rv
344
                        }
345
                        // The entry is Unusable; treat it as if it weren't there.
346
4
                        None => None,
347
                    }
348
                } else {
349
                    // The Entry::unwrap function will panic if its argument is
350
                    // Entry::Unusable.  But that is impossible in this case,
351
                    // since we already checked key_version_is_maximal() for this key,
352
                    // and our invariant guarantees that, if the value is Entry::Unusable,
353
                    // then key_version(key) == SATURATE_AT_VERSION,
354
                    // so key_version_is_maximal is true.
355
143266
                    self.base.remove(key).map(Entry::unwrap)
356
                }
357
143330
            }
358

            
359
            /// Remove every element of this map that does not satisfy a given predicate.
360
            ///
361
            /// See
362
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::retain()`].")]
363
212
            pub fn retain<F>(&mut self, mut f: F)
364
212
            where
365
212
                F: FnMut(K, &mut V) -> bool,
366
            {
367
252
                self.base.retain(|k, v| {
368
252
                    let Entry::Present(v_inner) = v else {
369
8
                        return true;
370
                    };
371

            
372
244
                    if f(k, v_inner) {
373
216
                        true
374
28
                    } else if key_version_is_maximal(k) {
375
12
                        self.n_unusable += 1;
376
12
                        *v = Entry::Unusable;
377
12
                        true
378
                    } else {
379
16
                        false
380
                    }
381
252
                });
382
212
            }
383

            
384
            /// Remove every element of this map.
385
            ///
386
            /// See
387
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::clear()`].")]
388
12
            pub fn clear(&mut self) {
389
12
                self.retain(|_, _| false);
390
12
            }
391

            
392
            /// Return a reference to the element of this map with a given key.
393
            ///
394
            /// Return None if there is no such element.
395
            ///
396
            /// See
397
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::get()`].")]
398
410
            pub fn get(&self, key: K) -> Option<&V> {
399
410
                self.base.get(key).and_then(Entry::value)
400
410
            }
401
            /// Return a mutable reference to the element of this map with a given key.
402
            ///
403
            /// Return None if there is no such element.
404
            ///
405
            /// See
406
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::get_mut()`].")]
407
36602226
            pub fn get_mut(&mut self, key: K) -> Option<&mut V> {
408
36602226
                self.base.get_mut(key).and_then(|ent| ent.value_mut())
409
36602226
            }
410

            
411
            /// Return an array of mutable references to the elements of this map with a given list
412
            /// of keys.
413
            ///
414
            /// Return None if any key is not present, or if the same key is given twice.
415
            ///
416
            /// See
417
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::get_disjoint_mut()`].")]
418
12
            pub fn get_disjoint_mut<const N: usize>(&mut self, keys: [K; N]) -> Option<[&mut V; N]> {
419
12
                let vals = self.base.get_disjoint_mut(keys)?;
420
                // TODO array::try_map would be preferable, but it isn't stable.
421
12
                if vals.iter().all(|e| matches!(e, Entry::Present(_))) {
422
                    // Cannot panic, since we checked that every entry is present.
423
8
                    Some(vals.map(|v| match v {
424
8
                        Entry::Present(v) => v,
425
                        Entry::Unusable => panic!("Logic error"),
426
8
                    }))
427
                } else {
428
4
                    None
429
                }
430
12
            }
431

            
432
            /// Return an iterator over the elements of this map.
433
            ///
434
            /// See
435
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::iter()`].")]
436
            ///
437
            /// # Current limitations
438
            ///
439
            /// Does not return a named type.
440
81992
            pub fn iter(&self) -> impl Iterator<Item = (K, &V)> + '_ {
441
83660
                self.base.iter().filter_map(|(k, v)| match v {
442
83648
                    Entry::Present(v) => Some((k, v)),
443
12
                    Entry::Unusable => None,
444
83660
                })
445
81992
            }
446

            
447
            /// Remove every element of this map.
448
            ///
449
            /// See
450
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::drain()`].")]
451
542
            pub fn drain(&mut self) -> impl Iterator<Item = (K, V)> + '_ {
452
726
                self.base.drain().filter_map(|(k, v)| match v {
453
412
                    Entry::Present(v) => Some((k, v)),
454
                    Entry::Unusable => None,
455
412
                })
456
542
            }
457

            
458
            /// Return a mutable iterator over the elements of this map.
459
            ///
460
            /// See
461
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::iter_mut()`].")]
462
            ///
463
            /// # Current limitations
464
            ///
465
            /// Does not return a named type.
466
36
            pub fn iter_mut(&mut self) -> impl Iterator<Item = (K, &mut V)> + '_ {
467
140
                self.base.iter_mut().filter_map(|(k, v)| match v {
468
136
                    Entry::Present(v) => Some((k, v)),
469
4
                    Entry::Unusable => None,
470
140
                })
471
36
            }
472

            
473
            /// Return an iterator over all the keys in this map.
474
            ///
475
            /// See
476
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::keys()`].")]
477
            ///
478
            /// # Current limitations
479
            ///
480
            /// Does not return a named type.
481
18
            pub fn keys(&self) -> impl Iterator<Item = K> + '_ {
482
18
                self.iter().map(|(k, _)| k)
483
18
            }
484

            
485
            /// Return an iterator over the values in this map.
486
            ///
487
            /// See
488
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::values()`].")]
489
            ///
490
            /// # Current limitations
491
            ///
492
            /// Does not return a named type.
493
20
            pub fn values(&self) -> impl Iterator<Item = &V> + '_ {
494
20
                self.base.values().filter_map(Entry::value)
495
20
            }
496

            
497
            /// Return a mutable iterator over the values in this map.
498
            ///
499
            /// See
500
            #[doc= concat!("[`slotmap::", stringify!($mapname), "::values_mut()`].")]
501
            ///
502
            /// # Current limitations
503
            ///
504
            /// Does not return a named type.
505
12
            pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> + '_ {
506
12
                self.base.values_mut().filter_map(Entry::value_mut)
507
12
            }
508

            
509
            /// Testing helper: Assert that every invariant holds for this map.
510
            ///
511
            /// # Panics
512
            ///
513
            /// Panics if any invariant does not hold.
514
            #[cfg(test)]
515
108
            fn assert_rep_ok(&self) {
516
108
                let mut n_unusable_found = 0;
517
188
                for (k, v) in self.base.iter() {
518
188
                    assert!(key_okay(k), "Key {:?} was invalid", k.data());
519
188
                    if matches!(v, Entry::Unusable) {
520
96
                        n_unusable_found += 1;
521
96
                        assert_eq!(key_version(k), SATURATE_AT_VERSION);
522
92
                    }
523
                }
524
108
                assert_eq!(n_unusable_found, self.n_unusable);
525
108
            }
526
        }
527

            
528
        /// Helper: a token constructed if the slotmap behavior matches our expectations.
529
        ///
530
        /// See `validate_*_behavior()`
531
        #[derive(Clone, Debug)]
532
        struct [<$mapname ValidationToken>];
533

            
534
        /// Spot-check whether `SlotMap` has changed its key encoding behavior; panic if so.
535
        ///
536
        /// (Our implementation relies on our ability to check whether a version number is about to
537
        /// overflow. But the only efficient way to access a version number is via `KeyData::as_ffi`,
538
        /// which does not guarantee anything about the actual encoding of the versions.)
539
        ///
540
        /// This function returns a ZST ValidationToken; nothing else must return one.
541
        /// Being able to construct a ValidationToken implies
542
        /// that `slotmap` has probably not changed its behavior in a way that will break us.
543
        ///
544
        /// # Panics
545
        ///
546
        /// May panic if slotmap does not encode its keys in the expected manner.
547
237462
        fn [<validate_ $mapname:snake _behavior>]() -> [<$mapname ValidationToken>] {
548
            use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
549
            /// Helper:
550
            static VALIDATED: AtomicBool = AtomicBool::new(false);
551
237462
            if VALIDATED.load(Relaxed) {
552
                // We have already validated it at least once.
553
235412
                return [<$mapname ValidationToken>];
554
2050
            }
555
            /// Helper: assert that key has bit 32 set.
556
6150
            fn ver_lsb_check<K: Key>(key: K) {
557
6150
                let (ver, _) = key_data::key_data_parts(key.data()).expect("slotmap has changed its serde representation");
558
6150
                assert_eq!(ver & 1, 1,
559
                    "Key version LSB not set as expected"
560
                );
561
6150
            }
562

            
563
2050
            let mut map = slotmap::$mapname::new();
564
2050
            let k1 = map.insert("a");
565
2050
            assert_eq!(key_version(k1), 0, "Keys do not begin with version 0.");
566
2050
            assert_eq!(key_slot(k1), 1, "Keys do not begin with index 1.");
567
2050
            ver_lsb_check(k1);
568

            
569
            // This is a basic correctness check.
570
2050
            map.remove(k1).expect("insert+remove failed");
571
2050
            let k2 = map.insert("b");
572
2050
            assert_eq!(key_slot(k1), key_slot(k2), "Slot not re-used as expected.");
573
2050
            assert_eq!(
574
2050
                key_version(k1) + 1,
575
2050
                key_version(k2),
576
                "Key version did not increment by 1 after slot reuse"
577
            );
578
2050
            ver_lsb_check(k2);
579

            
580
2050
            let k3 = map.insert("c");
581
2050
            assert_eq!(
582
2050
                key_version(k3),
583
                0,
584
                "A different slot did not begin with version 0.",
585
            );
586
2050
            assert_eq!(
587
2050
                key_slot(k3),
588
2050
                key_slot(k1) + 1,
589
                "Slots not allocated in expected order."
590
            );
591
2050
            ver_lsb_check(k3);
592

            
593
            // Remember that we've validated SlotMap.
594
2050
            VALIDATED.store(true, Relaxed);
595
2050
            [<$mapname ValidationToken>]
596
237462
        }
597
    }
598

            
599
    impl<K:Key, V> std::ops::Index<K> for $mapname<K,V> {
600
        type Output = V;
601
122
        fn index(&self, key: K) -> &V {
602
122
            self.get(key).expect("key invalid")
603
122
        }
604
    }
605
    impl<K:Key, V> std::ops::IndexMut<K> for $mapname<K,V> {
606
4
        fn index_mut(&mut self, key: K) -> &mut V {
607
4
            self.get_mut(key).expect("key invalid")
608
4
        }
609
    }
610
}} // END OF MACRO.
611

            
612
define_implementation! { SlotMap }
613

            
614
define_implementation! { DenseSlotMap }
615

            
616
/// Return true if this key is apparently valid.
617
///
618
/// We should use debug_assert! to test this on every new key, every time an entry is inserted.
619
///
620
/// If inserting an entry results in a _not_ valid key,
621
/// we have messed up, and allowed a version counter to grow too high.
622
191416
fn key_okay<K: Key>(key: K) -> bool {
623
191416
    key_version(key) <= SATURATE_AT_VERSION
624
191416
}
625

            
626
/// Return true if the version number for this key should not be allowed to grow any larger.
627
///
628
/// We should call this whenever we are about to remove an entry with a given key.
629
/// If it returns true, we should instead replace the entry with [`Entry::Unusable`]
630
143354
fn key_version_is_maximal<K: Key>(key: K) -> bool {
631
143354
    key_version(key) == SATURATE_AT_VERSION
632
143354
}
633
/// The maximal version that we allow a key to reach.
634
///
635
/// When it reaches this version, we do not remove the entry with the key any longer;
636
/// instead, when we would remove the entry, we instead set its value to [`Entry::Unusable`]
637
///
638
/// This value is deliberately chosen to be less than the largest possible value (`0x7fff_ffff`),
639
/// so that we can detect any bugs that would risk overflowing the version.
640
const SATURATE_AT_VERSION: u32 = 0x7fff_fffe;
641

            
642
/// Helper: return the slot of a key, assuming that the representation is as we expect.
643
///
644
/// Used for testing and verify functions.
645
10290
fn key_slot<K: Key>(key: K) -> u32 {
646
10290
    let (_, idx) =
647
10290
        key_data::key_data_parts(key.data()).expect("slotmap has changed its serde representation");
648
10290
    idx
649
10290
}
650

            
651
#[cfg(test)]
652
mod test {
653
    // @@ begin test lint list maintained by maint/add_warning @@
654
    #![allow(clippy::bool_assert_comparison)]
655
    #![allow(clippy::clone_on_copy)]
656
    #![allow(clippy::dbg_macro)]
657
    #![allow(clippy::mixed_attributes_style)]
658
    #![allow(clippy::print_stderr)]
659
    #![allow(clippy::print_stdout)]
660
    #![allow(clippy::single_char_pattern)]
661
    #![allow(clippy::unwrap_used)]
662
    #![allow(clippy::unchecked_time_subtraction)]
663
    #![allow(clippy::useless_vec)]
664
    #![allow(clippy::needless_pass_by_value)]
665
    #![allow(clippy::string_slice)] // See arti#2571
666
    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
667

            
668
    /// Create a new key, using `ver` as its version field (includes trailing 1)
669
    /// and `idx` as its index field.
670
    fn construct_key(ver: u32, idx: u32) -> slotmap::DefaultKey {
671
        let j = serde_json::json! {
672
            {
673
                "version": ver,
674
                "idx": idx,
675
            }
676
        };
677
        serde_json::from_value(j).expect("invalid representation")
678
    }
679

            
680
    /// Define a set of tests for one of the map variants, in a module named after that variant.
681
    macro_rules! tests_for {
682
            { $mapname:ident } => {paste::paste!{
683

            
684
            mod [<$mapname:snake>] {
685

            
686
                use slotmap::DefaultKey;
687
                use crate::*;
688

            
689
            #[test]
690
            fn validate() {
691
                let _tok = [<validate_ $mapname:snake _behavior>]();
692
            }
693

            
694
            #[test]
695
            fn empty() {
696
                let mut m: $mapname<DefaultKey, ()> = $mapname::default();
697

            
698
                for _ in 1..=3 {
699
                    assert_eq!(m.len(), 0);
700
                    assert!(m.is_empty());
701
                    m.assert_rep_ok();
702

            
703
                    let k1 = m.insert(());
704
                    let k2 = m.insert(());
705
                    let k3 = m.insert(());
706
                    m.remove(k1);
707
                    m.remove(k2);
708
                    m.remove(k3);
709
                }
710
            }
711

            
712
            fn construct_near_saturated_slotmap() -> ($mapname<DefaultKey, String>, DefaultKey, DefaultKey) {
713
                fn encode_ver(v: u32) -> u32 {
714
                    (v << 1) | 1
715
                }
716

            
717
                let json = serde_json::json! {
718
                    [
719
                        // sentinel entry.
720
                        { "value": null, "version": 0},
721
                        { "value": {"Present": "hello"}, "version": encode_ver(SATURATE_AT_VERSION) },
722
                        { "value": {"Present": "world"}, "version": encode_ver(SATURATE_AT_VERSION - 2) }
723
                    ]
724
                };
725

            
726
                let m = $mapname {
727
                    base: serde_json::from_value(json).expect("invalid json"),
728
                    n_unusable: 0,
729
                    _valid: [<validate_ $mapname:snake _behavior>](),
730
                };
731
                let mut k1 = None;
732
                let mut k2 = None;
733

            
734
                for (k, v) in m.iter() {
735
                    if v == "hello" {
736
                        k1 = Some(k);
737
                    }
738
                    if v == "world" {
739
                        k2 = Some(k);
740
                    }
741
                }
742
                let (k1, k2) = (k1.unwrap(), k2.unwrap());
743
                (m, k1, k2)
744
            }
745

            
746
            #[test]
747
            fn saturating() {
748
                let (mut m, k1, k2) = construct_near_saturated_slotmap();
749

            
750
                assert_eq!(key_version(k1), SATURATE_AT_VERSION);
751
                assert_eq!(key_version(k2), SATURATE_AT_VERSION - 2);
752

            
753
                // Replace k1, and make sure that the index is _not_ reused.
754
                let v = m.remove(k1);
755
                assert_eq!(v.unwrap(), "hello");
756
                assert!(matches!(m.base.get(k1), Some(Entry::Unusable)));
757
                let k1_new = m.insert("HELLO".into());
758
                assert_ne!(key_slot(k1), key_slot(k1_new));
759
                assert_eq!(key_version(k1_new), 0);
760
                assert!(matches!(m.base.get(k1), Some(Entry::Unusable)));
761
                assert_eq!(m.get(k1_new).unwrap(), "HELLO");
762
                assert!(m.get(k1).is_none());
763
                m.assert_rep_ok();
764

            
765
                // Replace k2 and make sure that that the index gets reused twice.
766
                let v = m.remove(k2);
767
                assert_eq!(v.unwrap(), "world");
768
                let k2_2 = m.insert("WoRlD".into());
769
                assert_eq!(key_version(k2_2), SATURATE_AT_VERSION - 1);
770
                m.remove(k2_2);
771
                m.assert_rep_ok();
772
                assert!(m.base.get(k2_2).is_none());
773
                let k2_3 = m.insert("WORLD".into());
774
                assert_eq!(key_slot(k2), key_slot(k2_2));
775
                assert_eq!(key_slot(k2), key_slot(k2_3));
776
                assert_eq!(key_version(k2_3), SATURATE_AT_VERSION);
777
                m.remove(k2_3);
778
                assert!(m.base.get(k2_2).is_none());
779
                m.assert_rep_ok();
780

            
781
                let k2_4 = m.insert("World!".into());
782
                assert!(matches!(m.base.get(k2_3), Some(Entry::Unusable)));
783
                assert_eq!(m.get(k2_4).unwrap(), "World!");
784
                assert_ne!(key_slot(k2_4), key_slot(k2));
785
                assert!(m.contains_key(k2_4));
786
                assert!(!m.contains_key(k2_3));
787
                m.assert_rep_ok();
788
            }
789

            
790
            #[test]
791
            fn insert_variations() {
792
                let mut m = $mapname::new();
793
                let k1 = m.insert("hello".to_string());
794
                let k2 = m.insert_with_key(|k| format!("{:?}", k));
795
                let k3 = m
796
                    .try_insert_with_key(|k| Result::<_, ()>::Ok(format!("{:?}", k)))
797
                    .unwrap();
798
                let () = m.try_insert_with_key(|_k| Err(())).unwrap_err();
799

            
800
                assert!(m.contains_key(k1));
801
                assert!(m.contains_key(k2));
802
                assert!(m.contains_key(k3));
803
                assert_eq!(m.len(), 3);
804
            }
805

            
806
            #[test]
807
            fn remove_large_but_bogus() {
808
                let mut m: $mapname<DefaultKey, String> = $mapname::with_capacity(0);
809
                let _k1 = m.insert("hello".to_string());
810
                // Construct a key with maximal version (so we would expect to freeze it),
811
                // but which won't actually be present.
812
                let k_fake = super::construct_key((SATURATE_AT_VERSION << 1) | 1, 1);
813

            
814
                let v = m.remove(k_fake);
815
                assert!(v.is_none());
816
                m.assert_rep_ok();
817
            }
818

            
819
            #[test]
820
            fn remove_many_times() {
821
                let (mut m, k1, _k2) = construct_near_saturated_slotmap();
822

            
823
                let mut n_removed = 0;
824
                for _ in 0..10 {
825
                    if m.remove(k1).is_some() {
826
                        n_removed += 1;
827
                    }
828
                    m.assert_rep_ok();
829
                    assert_eq!(m.n_unusable, 1);
830
                    assert_eq!(m.len(), 1);
831
                }
832
                assert_eq!(n_removed, 1);
833
            }
834

            
835
            #[test]
836
            fn clear() {
837
                let (mut m, k1, k2) = construct_near_saturated_slotmap();
838
                assert_eq!(m.len(), 2);
839
                assert_eq!(m.is_empty(), false);
840
                assert_eq!(m.n_unusable, 0);
841

            
842
                for _ in 0..=2 {
843
                    m.clear();
844
                    m.assert_rep_ok();
845

            
846
                    assert_eq!(m.len(), 0);
847
                    assert_eq!(m.is_empty(), true);
848
                    assert!(m.get(k1).is_none());
849
                    assert!(m.get(k2).is_none());
850
                    assert!(matches!(m.base.get(k1), Some(Entry::Unusable)));
851
                    assert_eq!(m.n_unusable, 1);
852
                }
853

            
854
                let k_next = m.insert("probe".into());
855
                assert_eq!(key_slot(k_next), key_slot(k2));
856
                assert_eq!(key_version(k_next), SATURATE_AT_VERSION - 1);
857
            }
858

            
859
            #[test]
860
            fn retain() {
861
                let (mut m, k1, k2) = construct_near_saturated_slotmap();
862

            
863
                // drop all but the nearly-saturated (but not saturated) "world" item.
864
                m.retain(|_k, v| v == "world");
865
                m.assert_rep_ok();
866
                assert_eq!(m.len(), 1);
867
                assert!(!m.is_empty());
868
                assert_eq!(m.n_unusable, 1);
869
                assert_eq!(m.contains_key(k1), false);
870
                assert_eq!(m.contains_key(k2), true);
871
                assert_eq!(m.base.contains_key(k1), true); // key still internally present as Unusable.
872

            
873
                let (mut m, k1, k2) = construct_near_saturated_slotmap();
874

            
875
                // drop all but the saturated (but not saturated) "hello" item.
876
                m.retain(|_k, v| v == "hello");
877
                m.assert_rep_ok();
878
                assert_eq!(m.len(), 1);
879
                assert!(!m.is_empty());
880
                assert_eq!(m.n_unusable, 0);
881
                assert_eq!(m.contains_key(k1), true);
882
                assert_eq!(m.contains_key(k2), false);
883
                assert_eq!(m.base.contains_key(k2), false); // key not present.
884
            }
885

            
886
            #[test]
887
            fn retain_and_panic() {
888
                use std::panic::AssertUnwindSafe;
889
                let (mut m, k1, _k2) = construct_near_saturated_slotmap();
890

            
891
                let _ = std::panic::catch_unwind(AssertUnwindSafe(|| {
892
                    m.retain(|k,_| if k == k1 { false } else { panic!() })
893
                })).unwrap_err();
894
                m.assert_rep_ok();
895
            }
896

            
897
            #[test]
898
            fn modify() {
899
                let (mut m, k1, k2) = construct_near_saturated_slotmap();
900

            
901
                *m.get_mut(k1).unwrap() = "HELLO".to_string();
902
                *m.get_mut(k2).unwrap() = "WORLD".to_string();
903

            
904
                let v: Vec<_> = m.values().collect();
905
                assert_eq!(v, vec![&"HELLO".to_string(), &"WORLD".to_string()]);
906
            }
907

            
908
            #[test]
909
            fn iterators() {
910
                let (mut m, k1, k2) = construct_near_saturated_slotmap();
911

            
912
                m.remove(k1);
913
                assert_eq!(m.n_unusable, 1);
914

            
915
                for v in m.values_mut() {
916
                    *v = "WORLD".to_string();
917
                }
918

            
919
                let v: Vec<_> = m.values().collect();
920
                assert_eq!(v, vec![&"WORLD".to_string()]);
921

            
922
                let v: Vec<_> = m.iter().collect();
923
                assert_eq!(v, vec![(k2, &"WORLD".to_string())]);
924

            
925
                for (k, v) in m.iter_mut() {
926
                    assert_eq!(k, k2);
927
                    *v = "World".to_string();
928
                }
929

            
930
                let v: Vec<_> = m.iter().collect();
931
                assert_eq!(v, vec![(k2, &"World".to_string())]);
932

            
933
                let v: Vec<_> = m.keys().collect();
934
                assert_eq!(v, vec![k2]);
935

            
936
                m.assert_rep_ok();
937
            }
938

            
939
            #[test]
940
            fn get_mut_multiple() {
941
                let (mut m, k1, k2) = construct_near_saturated_slotmap();
942

            
943
                assert!(m.get_disjoint_mut([k1,k1]).is_none());
944

            
945
                if let Some([v1, v2]) = m.get_disjoint_mut([k1, k2]) {
946
                    assert_eq!(v1, "hello");
947
                    assert_eq!(v2, "world");
948
                    *v1 = "HELLO".into();
949
                    *v2 = "WORLD".into();
950
                } else {
951
                    panic!("get_disjoint_mut failed.");
952
                };
953

            
954
                m.remove(k1);
955
                assert_eq!(m.contains_key(k1), false);
956
                assert_eq!(m.base.contains_key(k1), true);
957
                m.assert_rep_ok();
958

            
959
                if let Some([_v1, _v2]) = m.get_disjoint_mut([k1, k2]) {
960
                    panic!("get_disjoint_mut succeeded unexpectedly.")
961
                }
962
            }
963

            
964
            #[test]
965
            fn get_capacity() {
966
                let (mut m, k1, _) = construct_near_saturated_slotmap();
967

            
968
                let cap_orig = dbg!(m.capacity());
969
                m.remove(k1);
970
                m.assert_rep_ok();
971

            
972
                assert_eq!(m.n_unusable, 1);
973
                assert_eq!(m.capacity(), cap_orig - 1); // capacity decreased, since there is an unusable slot.
974

            
975
                m.reserve(5);
976
                assert!(m.capacity() >= 5);
977
            }
978

            
979
            #[test]
980
            fn index() {
981
                let (mut m, k1, k2) = construct_near_saturated_slotmap();
982

            
983
                assert_eq!(m[k1], "hello");
984
                assert_eq!(*(&mut m[k2]), "world");
985
            }
986
        } // end module.
987
        }}} // End macro rules
988

            
989
    tests_for! {SlotMap}
990
    tests_for! {DenseSlotMap}
991
}