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
#![warn(clippy::cognitive_complexity)]
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
//! <!-- @@ end lint list maintained by maint/add_warning @@ -->
49

            
50
mod key_data;
51

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

            
56
use key_data::key_version_serde as key_version;
57

            
58
//use key_version::key_version_serde;
59

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
611
define_implementation! { SlotMap }
612

            
613
define_implementation! { DenseSlotMap }
614

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
745
            #[test]
746
            #[allow(clippy::cognitive_complexity)]
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
}