mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 14:13:58 +00:00
Impl entry-API for la_arena::ArenaMap
We enforce integral and `Copy` key, so some key-related functions are not necessary since user can just reuse the index for the `entry` call.
This commit is contained in:
parent
c203ac2cf5
commit
10f870eff4
2 changed files with 108 additions and 1 deletions
|
@ -12,7 +12,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
mod map;
|
mod map;
|
||||||
pub use map::ArenaMap;
|
pub use map::{ArenaMap, Entry, OccupiedEntry, VacantEntry};
|
||||||
|
|
||||||
/// The raw index of a value in an arena.
|
/// The raw index of a value in an arena.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
|
|
@ -56,6 +56,16 @@ impl<T, V> ArenaMap<Idx<T>, V> {
|
||||||
self.v.iter().enumerate().filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?)))
|
self.v.iter().enumerate().filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the given key's corresponding entry in the map for in-place manipulation.
|
||||||
|
pub fn entry(&mut self, idx: Idx<T>) -> Entry<'_, Idx<T>, V> {
|
||||||
|
let idx = Self::to_idx(idx);
|
||||||
|
self.v.resize_with((idx + 1).max(self.v.len()), || None);
|
||||||
|
match &mut self.v[idx] {
|
||||||
|
slot @ Some(_) => Entry::Occupied(OccupiedEntry { slot, _ty: PhantomData }),
|
||||||
|
slot @ None => Entry::Vacant(VacantEntry { slot, _ty: PhantomData }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn to_idx(idx: Idx<T>) -> usize {
|
fn to_idx(idx: Idx<T>) -> usize {
|
||||||
u32::from(idx.into_raw()) as usize
|
u32::from(idx.into_raw()) as usize
|
||||||
}
|
}
|
||||||
|
@ -83,3 +93,100 @@ impl<T, V> Default for ArenaMap<Idx<V>, T> {
|
||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A view into a single entry in a map, which may either be vacant or occupied.
|
||||||
|
///
|
||||||
|
/// This `enum` is constructed from the [`entry`] method on [`ArenaMap`].
|
||||||
|
///
|
||||||
|
/// [`entry`]: ArenaMap::entry
|
||||||
|
pub enum Entry<'a, IDX, V> {
|
||||||
|
/// A vacant entry.
|
||||||
|
Vacant(VacantEntry<'a, IDX, V>),
|
||||||
|
/// An occupied entry.
|
||||||
|
Occupied(OccupiedEntry<'a, IDX, V>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, IDX, V> Entry<'a, IDX, V> {
|
||||||
|
/// Ensures a value is in the entry by inserting the default if empty, and returns a mutable reference to
|
||||||
|
/// the value in the entry.
|
||||||
|
pub fn or_insert(self, default: V) -> &'a mut V {
|
||||||
|
match self {
|
||||||
|
Self::Vacant(ent) => ent.insert(default),
|
||||||
|
Self::Occupied(ent) => ent.into_mut(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ensures a value is in the entry by inserting the result of the default function if empty, and returns
|
||||||
|
/// a mutable reference to the value in the entry.
|
||||||
|
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
|
||||||
|
match self {
|
||||||
|
Self::Vacant(ent) => ent.insert(default()),
|
||||||
|
Self::Occupied(ent) => ent.into_mut(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Provides in-place mutable access to an occupied entry before any potential inserts into the map.
|
||||||
|
pub fn and_modify<F: FnOnce(&mut V)>(mut self, f: F) -> Self {
|
||||||
|
if let Self::Occupied(ent) = &mut self {
|
||||||
|
f(ent.get_mut());
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, IDX, V> Entry<'a, IDX, V>
|
||||||
|
where
|
||||||
|
V: Default,
|
||||||
|
{
|
||||||
|
/// Ensures a value is in the entry by inserting the default value if empty, and returns a mutable reference
|
||||||
|
/// to the value in the entry.
|
||||||
|
pub fn or_default(self) -> &'a mut V {
|
||||||
|
self.or_insert_with(Default::default)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A view into an vacant entry in a [`ArenaMap`]. It is part of the [`Entry`] enum.
|
||||||
|
pub struct VacantEntry<'a, IDX, V> {
|
||||||
|
slot: &'a mut Option<V>,
|
||||||
|
_ty: PhantomData<IDX>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, IDX, V> VacantEntry<'a, IDX, V> {
|
||||||
|
/// Sets the value of the entry with the `VacantEntry`’s key, and returns a mutable reference to it.
|
||||||
|
pub fn insert(self, value: V) -> &'a mut V {
|
||||||
|
self.slot.insert(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A view into an occupied entry in a [`ArenaMap`]. It is part of the [`Entry`] enum.
|
||||||
|
pub struct OccupiedEntry<'a, IDX, V> {
|
||||||
|
slot: &'a mut Option<V>,
|
||||||
|
_ty: PhantomData<IDX>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, IDX, V> OccupiedEntry<'a, IDX, V> {
|
||||||
|
/// Gets a reference to the value in the entry.
|
||||||
|
pub fn get(&self) -> &V {
|
||||||
|
self.slot.as_ref().expect("Occupied")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets a mutable reference to the value in the entry.
|
||||||
|
pub fn get_mut(&mut self) -> &mut V {
|
||||||
|
self.slot.as_mut().expect("Occupied")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts the entry into a mutable reference to its value.
|
||||||
|
pub fn into_mut(self) -> &'a mut V {
|
||||||
|
self.slot.as_mut().expect("Occupied")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the value of the entry with the `OccupiedEntry`’s key, and returns the entry’s old value.
|
||||||
|
pub fn insert(&mut self, value: V) -> V {
|
||||||
|
self.slot.replace(value).expect("Occupied")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes the value of the entry out of the map, and returns it.
|
||||||
|
pub fn remove(self) -> V {
|
||||||
|
self.slot.take().expect("Occupied")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue