Skip to content

feat: added Arena::next_index - #54

Closed
sanbox-irl wants to merge 3 commits into
LPGhatguy:mainfrom
sanbox-irl:push-orxvtnwwyvuq
Closed

feat: added Arena::next_index#54
sanbox-irl wants to merge 3 commits into
LPGhatguy:mainfrom
sanbox-irl:push-orxvtnwwyvuq

Conversation

@sanbox-irl

Copy link
Copy Markdown
Contributor

Added two useful methods:

Arena::vacant_entry which makes a new Entry while computing the next key
Arena::next_index which immutably takes Arena and calculates what the next key would be.

There's some testing for this but I didn't go sicko mode.

I also edited the Changelog but i'm not sure if you'd prefer to do that yourself!

@sanbox-irl

Copy link
Copy Markdown
Contributor Author

also @mikwielgus going to ping you here since you wrote the Entry API

Comment thread CHANGELOG.md Outdated
@mikwielgus

Copy link
Copy Markdown
Contributor

@sanbox-irl thanks for the ping. Why do you need this?

@sanbox-irl

Copy link
Copy Markdown
Contributor Author

@mikwielgus For self-referential inserts. Basically you can now make:

let mut a: Arena<Index> = Arena::new();
a.insert(a.next_index());

Obviously this is a silly example.

This is also the equivalent of https://docs.rs/slab/latest/slab/struct.Slab.html#method.vacant_key

Comment thread src/arena.rs Outdated
Comment thread src/arena.rs
}
} else {
let slot: u32 = self.storage.len().try_into().unwrap_or_else(|_| {
unreachable!("Arena storage exceeded what can be represented by a u32")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exceeding storage size is not really unreachable, so I'd use .expect() here instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what Arena::insert uses, and I'd rather copy what it does there.

@mikwielgus

Copy link
Copy Markdown
Contributor

One more comment:

An alternative interface would be something like SlotMap::insert_with_key(). This would avoid creating an Index that points to nothing and is instantly invalidated with insertions and removals (notice that Index currently has no ::new() constructor -- this is probably intentional, to make it less likely for the library user to construct an invalid Index).

@sanbox-irl

Copy link
Copy Markdown
Contributor Author

Yes, I am also okay with that approach, though I think vacant_entry and next_index should be split in that case -- i think vacant_entry is a good idea no matter what, but next_index might be better done with insert_with_key

@mikwielgus

Copy link
Copy Markdown
Contributor

Yes, I am also okay with that approach, though I think vacant_entry and next_index should be split in that case -- i think vacant_entry is a good idea no matter what, but next_index might be better done with insert_with_key

Yes, I agree that .vacant_entry() itself is a good addition.

@LPGhatguy

Copy link
Copy Markdown
Owner

vacant_entry is a great API and seems great to have.

Given that vacant_entry can give you the index, do we need next_index? @sanbox-irl's example can be written as:

let mut a: Arena<Index> = Arena::new();
let entry = a.vacant_entry();
entry.insert(entry.key());

of course this means that a mutable borrow to the Arena for a bit.

@LPGhatguy

Copy link
Copy Markdown
Owner

Also an unrelated note: we should really rename all the APIs that have the name key to use index instead, or we do the more disruptive option and rename Index to Key.

@sanbox-irl

sanbox-irl commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

of course this means that a mutable borrow to the Arena for a bit.

Yeah that's pretty much the reason to have the alternative. Getting to skip that mutable borrow can make this kind of code incredibly simpler.

For my particular use case though, I could also use something like insert_with_id.

Generally though, this seems weird, but this is as simple of an operation as doing:

let mut my_vec_of_indices: Vec<usize> = vec![];
let next_key = my_vec.len();
my_vec.push(next_key);

I think of Arena as basically just a space optimizing version of this Vec example, and so its API should be roughly similar, and so I think there should be a trivial way to ask "hey what's the next key I'm going to get"

@sanbox-irl sanbox-irl closed this Aug 18, 2026
@sanbox-irl
sanbox-irl deleted the push-orxvtnwwyvuq branch August 18, 2026 12:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants