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
/*!
This crate mainly deals with issuing and maintaining stability of indices.
It provides 4 structs and each helps in different area.

This library was created for my game development endeavor.
Not going great on that front as I kept restarting the project.
However, I saw these utility structures coming back multiple times so I'm making a crate for them.

In version 0.2.0, you can supply custom Id tuple structs that are based on unsigned integers (from 8bit to 64bits).
The id type needs to be derived with the following:
```
// Minimal needed for all traits that are introduced by this crate.
#[derive(derive_stable_id::StableId)]
struct Id(u8);


// These are needed under normal circumstances.
#[derive(derive_stable_id::StableId)]
struct Id32(u32);

let x: stable_id::Eids<Id32> = Default::default();
let x: stable_id::Sequence<Id32> = Default::default();
let x: stable_id::SparseEntities<Id32, String> = Default::default();
let x: stable_id::Entities<Id32, String> = Default::default();
let x: stable_id::Tec<Id32, String> = Default::default();
```

# Use cases
| Struct                | Type          | Suggestion    | Description |
| -----------           | ----          | ----          |-----------  |
| [`Eids`]              | Id            | Dense data    | You want a way to create ids, and **do** care about recovering ids. |
| [`Sequence`]          | Id            | Sparse data   | You want a way to create ids, and **don't** care about recovering ids, but you don't want to use the HashMap-based [`Entities`] struct. |
| [`Entities`]          | Collection    | Dense data    | The go-to collection of this library.
| [`SparseEntities`]    | Collection    | Sparse data   | You want mix sequence (ids not recycled) and HashMap together. |
| [`Tec`]               | Collection    | Dense data    | You want to use a vec to store data, but need constant entity removal. [`Tec`] reclaims the spaces for you as you insert more new items.
 */
use std::collections::BTreeSet;

use rustc_hash::FxHashMap;

pub use derive_stable_id::StableId;
pub use stable_id_traits::*;

mod eids;
mod entities;
mod sequence;
mod sparse_entities;
mod tomb_vec;

/**
Stands for Entity Id generator (ids are redeemable).
Basically a counter with a B-tree based free "set" (list).

# Use case
- you want to recycle ids due to frequent entity removal
- you want to use custom data structure but need id management
- ids start from zero

# Example
```
use stable_id::Eids;

let mut entities: Eids<u8> = Default::default();
let id = entities.claim();
entities.unclaim(id);
```

See [`Self::coalesce()`] if you want to pack ids together, like when you're trying to tighten up an array and
saving it into a database/save file (i.e. when game players are saving their progress).
*/
#[derive(Clone, Default)]
pub struct Eids<IndexT>
where
    IndexT: Ord,
{
    freed: BTreeSet<IndexT>,
    next: IndexT,
}

/**
An abstracted monotonically increasing counter structure.
Once you claim an id you can't go back.

# Example
```
use stable_id::Sequence;

let mut s: Sequence<u8> = Default::default();
assert_eq!(s.next_value(), 0);
assert_eq!(s.next_value(), 1);
assert_eq!(s.next_value(), 2);

let mut s = Sequence::continue_from(1234u16);
assert_eq!(s.next_value(), 1234);
assert_eq!(s.next_value(), 1235);
assert_eq!(s.next_value(), 1236);
```
 */
#[derive(Clone, Default)]
pub struct Sequence<IndexT> {
    counter: IndexT,
}

/// inspired by https://github.com/fitzgen/generational-arena/blob/72975c8355949c2338976d944e047c9d9f447174/src/lib.rs#L178
/// but without the generation stuff.
#[derive(Clone, Debug)]
pub(crate) enum Slot<DataT, IndexT> {
    Dead { next_free: IndexT },
    Alive(DataT),
}

/**
Short for [tombstone](https://en.wikipedia.org/wiki/Tombstone_(programming))-based vector.
Inspired by [generational-arena](https://github.com/fitzgen/generational-arena/blob/72975c8355949c2338976d944e047c9d9f447174/src/lib.rs#L178), but without the generation stuff.

# Features
- index stability when deleting an element
- maintain freed list, and is basically free for large structs

Use case: you have compact data that needs to be inserted & deleted while other objects maintain their index-based references.

Don't use it if:
- the data are sparse (use a HashMap or [`Entities`] instead)
- you don't need to remove data (use a Vec **with** [`Sequence`] instead)

```
use stable_id::Tec;

// use the `derive_more` crate to shortern the list
#[derive(derive_stable_id::StableId, Debug)]
struct Id(u8);
struct Data { field: usize }

let mut storage: Tec<Id, Data> = Default::default();
assert_eq!(storage.alloc(Data {field: 123}), Id(0));
assert_eq!(storage.get(Id(0)).unwrap().field, 123);
```
*/
#[derive(Clone)]
pub struct Tec<IndexT, DataT> {
    vec: Vec<Slot<DataT, IndexT>>,
    /// invariants: the free index must be either
    ///      - pointer some dead slot within the `vec`
    ///      - or the sentinal value of Maximum::maximum()
    /// In other words, the `vec` cannot have trailing dead slots
    next_free: IndexT,
    count: usize,
}

/**
This is a sandwich of HashMap and [`Sequence`].

# Features:
- stable indices and not redeemable
- generated indices

Use cases:
- you're removing more entities than you are adding
- you don't care about relaiming ids
*/
pub struct SparseEntities<IndexT, DataT> {
    data: FxHashMap<IndexT, DataT>,
    seq: Sequence<IndexT>,
}

/**
This is a lazily memory-compact version of [`SparseEntities`].
Use cases are the same but there are different tradeoffs.


# Tradeoff vs [`SparseEntities`].
- this struct uses a hash-based virtual table to translate issued ids into an id used internally by its backing collection [`Tec`].
  So accessing items should be similar -- it's dictated by HashMap's access complexity, since once it finds
  the internal id, a random access follows.
- removing items is O([`Tec::remove()`]) = O(n lg n) though I have plans to make it O(n). An added benefits is [`remove()`] will also
  try to compact the memory by removing dead slots from [`Tec`] when there's a majority of dead slots -- it's another O(n) pass.
*/
#[derive(Clone)]
pub struct Entities<IndexT, DataT> {
    vtable: FxHashMap<IndexT, IndexT>, // virtual id -> physical id
    data: Tec<IndexT, DataT>,
    seq: Sequence<IndexT>,
}