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
#![warn(clippy::or_fun_call)]
28
#![deny(clippy::print_stderr)]
29
#![deny(clippy::print_stdout)]
30
#![warn(clippy::rc_buffer)]
31
#![deny(clippy::ref_option_ref)]
32
#![warn(clippy::semicolon_if_nothing_returned)]
33
#![warn(clippy::trait_duplication_in_bounds)]
34
#![deny(clippy::unchecked_time_subtraction)]
35
#![deny(clippy::unnecessary_wraps)]
36
#![warn(clippy::unseparated_literal_suffix)]
37
#![deny(clippy::unwrap_used)]
38
#![deny(clippy::mod_module_files)]
39
#![allow(clippy::let_unit_value)] // This can reasonably be done for explicitness
40
#![allow(clippy::uninlined_format_args)]
41
#![allow(clippy::significant_drop_in_scrutinee)] // arti/-/merge_requests/588/#note_2812945
42
#![allow(clippy::result_large_err)] // temporary workaround for arti#587
43
#![allow(clippy::needless_raw_string_hashes)] // complained-about code is fine, often best
44
#![allow(clippy::needless_lifetimes)] // See arti#1765
45
#![allow(mismatched_lifetime_syntaxes)] // temporary workaround for arti#2060
46
#![allow(clippy::collapsible_if)] // See arti#2342
47
#![deny(clippy::unused_async)]
48
#![deny(clippy::string_slice)] // See arti#2571
49
#![allow(recursion_depth_exceeding_limit)] // arti#2715, rust/issues/159228
50
//! <!-- @@ end lint list maintained by maint/add_warning @@ -->
51

            
52
mod key_data;
53

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

            
58
use key_data::key_version_serde as key_version;
59

            
60
//use key_version::key_version_serde;
61

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
373
122
                    if f(k, v_inner) {
374
108
                        true
375
14
                    } else if key_version_is_maximal(k) {
376
6
                        self.n_unusable += 1;
377
6
                        *v = Entry::Unusable;
378
6
                        true
379
                    } else {
380
8
                        false
381
                    }
382
126
                });
383
106
            }
384

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
613
define_implementation! { SlotMap }
614

            
615
define_implementation! { DenseSlotMap }
616

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
937
                m.assert_rep_ok();
938
            }
939

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

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

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

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

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

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

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

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

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

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

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

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