1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
//! [`GenMap`] is a configurable generational map that stores each value in a slot
//! and hands out a [`Key`] that points at that slot.
//!
//! When a value is removed, the map frees its slot and may reuse
//! that slot for a value inserted later. The key of the removed value stops
//! matching the slot when the value is removed, so it does not match the value
//! the map later puts in that slot either. That makes keys safe to hold on to
//! where plain indices or references are not, such as in graphs, entity
//! systems and anything else that refers to values by handle.
//! [How it works](#how-it-works) lists the few cases where a key can match a
//! value other than the one it was handed out for.
//!
//! Inserting, removing and looking up a value are all O(1). The crate never
//! uses `std`, and [Cargo features](#cargo-features) lists the features that
//! need an allocator.
//!
//! # Examples
//!
//! ```
//! use gen_map::GenMap;
//!
//! let mut map = GenMap::new();
//! let a = map.insert("a");
//! let b = map.insert("b");
//! assert_eq!(map[a], "a");
//!
//! assert_eq!(map.remove(a), Some("a"));
//! assert!(map.get(a).is_none());
//!
//! // The map puts "c" in the slot that "a" was removed from. The key `a`
//! // stopped matching that slot when "a" was removed, so it does not match
//! // "c".
//! let c = map.insert("c");
//! assert_eq!(c.idx(), a.idx());
//! assert!(map.get(a).is_none());
//! assert_eq!(map[c], "c");
//!
//! // The iterator yields each value with its key, in slot order. "c" is in the
//! // first slot, so it comes before "b".
//! let pairs: Vec<_> = map.iter().collect();
//! assert_eq!(pairs, [(c, &"c"), (b, &"b")]);
//! ```
//!
//! A [`SecondaryMap`] stores values under the keys a [`GenMap`] hands out.
//!
//! ```
//! use gen_map::{GenMap, SecondaryMap};
//!
//! let mut people = GenMap::new();
//! let mut ages = SecondaryMap::new();
//! let alice = people.insert("Alice");
//! ages.insert(alice, 30).unwrap();
//! assert_eq!(ages[alice], 30);
//! ```
//!
//! A config decides the size of a map's keys and the collection the map keeps
//! its slots in.
//!
//! ```
//! use gen_map::{GenMap, GenMapConfig, GenSlotItem, MapConfig, Split};
//!
//! /// Maps with this config hand out keys with a `u8` index and a `u8`
//! /// generation, so each key is two bytes. A map with this config never gives
//! /// a slot the index `u8::MAX`, so it holds at most 255 slots.
//! struct Tiny;
//!
//! impl MapConfig for Tiny {
//! type KeyConfig = Split<u8, u8>;
//! }
//!
//! impl<S: GenSlotItem> GenMapConfig<S> for Tiny {
//! type Storage = Vec<S>;
//! }
//!
//! let mut map = GenMap::<u64, Tiny>::new_with_config();
//! let key = map.insert(7);
//! assert_eq!(core::mem::size_of_val(&key), 2);
//! assert_eq!(map[key], 7);
//! ```
//!
//! # How it works
//!
//! A key holds the index of its value's slot and the generation that slot had
//! when the key was handed out. A key only matches its slot while the slot's
//! generation equals the key's. A new slot starts at generation zero, and the
//! map adds one to a slot's generation when it inserts a value into the slot
//! and again when [`remove`](GenMap::remove) takes the value out. So the
//! generation is odd while the slot holds a value and even while it does not.
//! Once a value is removed, no copy of its key matches the slot, and the key
//! the map hands out for the next value in that slot has a newer generation.
//!
//! The map keeps a slot after its value is removed, and it reuses freed slots
//! before it adds new ones. Only [`reset`](GenMap::reset) removes slots. The
//! iterators, [`retain`](GenMap::retain), [`drain`](GenMap::drain) and
//! [`clear`](GenMap::clear) go through every slot, including the ones that
//! hold no value, so the time they take follows
//! [`slots_len`](GenMap::slots_len) rather than [`len`](GenMap::len).
//!
//! The map adds one to a slot's generation twice for each value, so a `u32`
//! generation lets a slot hold over two billion values one after another, and
//! a 4-bit generation lets it hold eight. When the map removes a value whose
//! key has the largest generation its key config can hold, the slot has no
//! generations left. By default, the map then retires the slot and never uses
//! it again. When [`WRAP_ON_OVERFLOW`](GenMapConfig::WRAP_ON_OVERFLOW) is
//! `true`, the map instead starts the slot's generation over at zero and keeps
//! using the slot. The map then counts the slot's generation up through the
//! same values again, so a key from before the wrap can match a new value once
//! the slot's generation is back at the key's.
//!
//! Two methods also let a key match a value other than the one it was handed
//! out for. [`reset`](GenMap::reset) removes every slot and starts the
//! generations over, so a key from before the reset can match a value inserted
//! after it. [`reattach`](GenMap::reattach) puts any value under a key whose
//! value [`detach`](GenMap::detach) took out, and the key then matches that
//! value.
//!
//! # Configuring the map
//!
//! A map's config is a type that implements [`MapConfig`] and
//! [`GenMapConfig`]. The map only uses the config as a type and never creates
//! a value of it, so an empty struct is enough. A config decides three things.
//!
//! - [`KeyConfig`](MapConfig::KeyConfig) decides the integer types of a key's
//! index and generation, and how the key stores the two. [`Split`] keeps
//! them as two fields, and [`Packed`] puts them in the bits of one integer.
//! With either key config, `Option<Key>` is the same size as `Key`.
//! - [`WRAP_ON_OVERFLOW`](GenMapConfig::WRAP_ON_OVERFLOW) decides whether the
//! map retires a slot with no generations left or starts its generation over
//! at zero.
//! - [`Storage`](GenMapConfig::Storage) is the collection the map keeps its
//! slots in. It can be a `Vec`, an `ArrayVec`, a `SmallVec` or any other
//! type that implements [`SlotStorage`].
//!
//! When its `C` parameter is left out, as in `GenMap<T>`, a map uses
//! [`DefaultMapConfig`]. Maps with that config hand out keys with a `u32`
//! index and a `u32` generation, keep their slots in a `Vec` and retire a slot
//! that has no generations left. [`GenMap::new`] only exists for the default
//! config, so use [`GenMap::new_with_config`] for any other.
//!
//! Maps whose configs have the same key config share a key type. A key does
//! not record which map handed it out, so a map also accepts keys from another
//! map with the same key config, and it may hold an unrelated value under such
//! a key.
//!
//! # Secondary maps
//!
//! Use a [`SecondaryMap`] to add data to the values of a [`GenMap`] without
//! changing their type. A `SecondaryMap` can only use a `GenMap`'s keys when
//! both configs have the same [`KeyConfig`](MapConfig::KeyConfig), because
//! only then do the two maps share a key type.
//!
//! When a value is removed from the `GenMap`, the value stored under its key
//! stays in the `SecondaryMap`. If the `GenMap` later puts a new value in the
//! removed value's slot, the new value's key has the same index as the old key
//! and a newer generation. The
//! [`ReplaceStrategy`](SecondaryMapConfig::ReplaceStrategy) of the
//! `SecondaryMap`'s config decides whether a value inserted under that newer
//! key replaces the old value.
//!
//! # Cargo features
//!
//! - `alloc` is on by default. It adds the `Vec` storage and
//! [`DefaultMapConfig`]. Without it, every map needs a config of its own.
//! - `arrayvec` lets a config use `arrayvec::ArrayVec` as its storage. An
//! `ArrayVec` has a fixed capacity and never allocates.
//! - `smallvec` lets a config use `smallvec::SmallVec` as its storage. A
//! `SmallVec` keeps its first slots inline and allocates when it needs room
//! for more. This feature uses the 2.0 beta of `smallvec`. Until `smallvec`
//! 2.0 is released, a newer beta or a new release of `gen_map` may break
//! this feature, so it is not covered by semver.
//!
//! The crate only needs an allocator when `alloc` or `smallvec` is on. To use
//! the crate without any allocator, turn default features off and `arrayvec`
//! on.
//!
//! ```toml
//! [dependencies]
//! gen_map = { version = "0.3", default-features = false, features = ["arrayvec"] }
//! ```
//!
//! # Minimum supported Rust version
//!
//! The crate builds on Rust 1.79 and later. The `smallvec` feature needs
//! Rust 1.86, because the 2.0 beta of `smallvec` does.
extern crate alloc;
extern crate std;
pub use DefaultMapConfig;
pub use ;
pub use ;
pub use Key;
pub use ;
pub use KeyPiece;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
// The tests use `Vec` storage and the default config, so they need `alloc`.