| Crates.io | alot |
| lib.rs | alot |
| version | 0.3.2 |
| created_at | 2023-05-03 03:48:01.896343+00 |
| updated_at | 2024-10-04 17:13:45.27411+00 |
| 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.