Crates.io | alot |
lib.rs | alot |
version | 0.3.2 |
source | src |
created_at | 2023-05-03 03:48:01.896343 |
updated_at | 2024-10-04 17:13:45.27411 |
description | A forbid-unsafe, generational slot map with usize-sized IDs |
homepage | |
repository | https://github.com/khonsulabs/alot |
max_upload_size | |
id | 855107 |
size | 65,881 |
A set of collections for storing values in a map-like structure using generated
unique keys. The base collection type, Lots<T>
, returns a LotId
for each
stored value. The stored values can be retrieved or removed using their LotId
.
This collection provides insert and read performance comparable to Vec<T>
, but
does not guarantee anything about the order of the contained values.
If ordering is needed, OrderedLots<T>
is provided which tracks the order of
elements while still allowing lookups by LotId
. Removing a value by its
LotId
becomes an O(n) operation with this collection.
Lots<T>
: Unordered collection of Tuse alot::Lots;
let mut map = Lots::new();
// Similar to a Vec, push adds a new value to the collection.
let greeting = map.push("hello, world");
// Prints: Greeting: LotId { generation: 1, index: 0 }
println!("Greeting: {greeting:?}");
// Values can be retrieved by their LotId.
assert_eq!(map[greeting], "hello, world");
OrderedLots<T>
: Ordered collection of Tuse alot::OrderedLots;
let mut map = OrderedLots::new();
// Values stored in OrderedLots can be accessed by index or by their LotId.
let c = map.push("c");
let a = map.push("a");
assert_eq!(map[c], map[0]);
// With OrderedLots, values can be inserted as well as pushed.
let b = map.insert(1, "b");
assert_eq!(map, &["c", "b", "a"]);
// OrderedLots also provides sorting functions.
map.sort();
assert_eq!(map, &["a", "b", "c"]);
There are several approaches to "slot maps" or "generational arenas" or other similarly named structures. This crate takes two approaches that make it unique:
LotId
is a single usize
. Most slot maps use usize
for indicies, and an
additional usize
for the generation.usize
for the generation, and many incur an additional byte of
overhead due to using Option<T>
.Vec<usize>
, rather than attempting to reuse the empty
slot's space. This was chosen for these advantages:
SlotData
enum to take up
more space than it currently does when size_of::<T>()
is less than the
size of a usize
. For example, the internal slot storage for Lots<u16>
uses 4 bytes per value.These design choices cause these limitations on this implementation:
usize
. In general, this isn't
a real limitation as allocating a contiguous region of memory that spans 75%
of the target architecture's RAM isn't practical. On a 64-bit platform,
Lots<T>
can hold 2^48 items -- 281 trillion items.usize
for generations, this
implementation will be more likely to return data for a stale ID due to the
generation rotating.