mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 05:38:46 +00:00
Merge #7274
7274: Flesh out la-arena crate r=lnicola a=arzg As requested in #7267, I’ve added some basic documentation and added more keys to the crate’s `Cargo.toml`. Co-authored-by: Aramis Razzaghipour <aramisnoah@gmail.com>
This commit is contained in:
commit
986e8e9e5a
3 changed files with 88 additions and 4 deletions
|
@ -3,8 +3,8 @@ name = "la-arena"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "Thy rope of sands..."
|
description = "Thy rope of sands..."
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
repository = "https://github.com/rust-analyzer/rust-analyzer"
|
||||||
|
documentation = "https://docs.rs/la-arena"
|
||||||
|
categories = ["data-structures", "memory-management", "rust-patterns"]
|
||||||
authors = ["rust-analyzer developers"]
|
authors = ["rust-analyzer developers"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[lib]
|
|
||||||
doctest = false
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
//! Yet another index-based arena.
|
//! Yet another ID-based arena.
|
||||||
|
|
||||||
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt,
|
fmt,
|
||||||
|
@ -10,6 +12,7 @@ use std::{
|
||||||
|
|
||||||
pub mod map;
|
pub mod map;
|
||||||
|
|
||||||
|
/// The raw ID of a value in an arena.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct RawId(u32);
|
pub struct RawId(u32);
|
||||||
|
|
||||||
|
@ -37,6 +40,7 @@ impl fmt::Display for RawId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The ID of a value allocated in an arena that holds `T`s.
|
||||||
pub struct Idx<T> {
|
pub struct Idx<T> {
|
||||||
raw: RawId,
|
raw: RawId,
|
||||||
_ty: PhantomData<fn() -> T>,
|
_ty: PhantomData<fn() -> T>,
|
||||||
|
@ -73,14 +77,18 @@ impl<T> fmt::Debug for Idx<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Idx<T> {
|
impl<T> Idx<T> {
|
||||||
|
/// Creates a new ID from a [`RawId`].
|
||||||
pub fn from_raw(raw: RawId) -> Self {
|
pub fn from_raw(raw: RawId) -> Self {
|
||||||
Idx { raw, _ty: PhantomData }
|
Idx { raw, _ty: PhantomData }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts this ID into the underlying [`RawId`].
|
||||||
pub fn into_raw(self) -> RawId {
|
pub fn into_raw(self) -> RawId {
|
||||||
self.raw
|
self.raw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Yet another ID-based arena.
|
||||||
#[derive(Clone, PartialEq, Eq)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
pub struct Arena<T> {
|
pub struct Arena<T> {
|
||||||
data: Vec<T>,
|
data: Vec<T>,
|
||||||
|
@ -93,29 +101,99 @@ impl<T: fmt::Debug> fmt::Debug for Arena<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Arena<T> {
|
impl<T> Arena<T> {
|
||||||
|
/// Creates a new empty arena.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let arena: la_arena::Arena<i32> = la_arena::Arena::new();
|
||||||
|
/// assert!(arena.is_empty());
|
||||||
|
/// ```
|
||||||
pub const fn new() -> Arena<T> {
|
pub const fn new() -> Arena<T> {
|
||||||
Arena { data: Vec::new() }
|
Arena { data: Vec::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Empties the arena, removing all contained values.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let mut arena = la_arena::Arena::new();
|
||||||
|
///
|
||||||
|
/// arena.alloc(1);
|
||||||
|
/// arena.alloc(2);
|
||||||
|
/// arena.alloc(3);
|
||||||
|
/// assert_eq!(arena.len(), 3);
|
||||||
|
///
|
||||||
|
/// arena.clear();
|
||||||
|
/// assert!(arena.is_empty());
|
||||||
|
/// ```
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.data.clear();
|
self.data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the length of the arena.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let mut arena = la_arena::Arena::new();
|
||||||
|
/// assert_eq!(arena.len(), 0);
|
||||||
|
///
|
||||||
|
/// arena.alloc("foo");
|
||||||
|
/// assert_eq!(arena.len(), 1);
|
||||||
|
///
|
||||||
|
/// arena.alloc("bar");
|
||||||
|
/// assert_eq!(arena.len(), 2);
|
||||||
|
///
|
||||||
|
/// arena.alloc("baz");
|
||||||
|
/// assert_eq!(arena.len(), 3);
|
||||||
|
/// ```
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.data.len()
|
self.data.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether the arena contains no elements.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let mut arena = la_arena::Arena::new();
|
||||||
|
/// assert!(arena.is_empty());
|
||||||
|
///
|
||||||
|
/// arena.alloc(0.5);
|
||||||
|
/// assert!(!arena.is_empty());
|
||||||
|
/// ```
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.data.is_empty()
|
self.data.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Allocates a new value on the arena, returning the value’s ID.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let mut arena = la_arena::Arena::new();
|
||||||
|
/// let id = arena.alloc(50);
|
||||||
|
///
|
||||||
|
/// assert_eq!(arena[id], 50);
|
||||||
|
/// ```
|
||||||
pub fn alloc(&mut self, value: T) -> Idx<T> {
|
pub fn alloc(&mut self, value: T) -> Idx<T> {
|
||||||
let id = RawId(self.data.len() as u32);
|
let id = RawId(self.data.len() as u32);
|
||||||
self.data.push(value);
|
self.data.push(value);
|
||||||
Idx::from_raw(id)
|
Idx::from_raw(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator over the arena’s elements.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let mut arena = la_arena::Arena::new();
|
||||||
|
/// let id1 = arena.alloc(20);
|
||||||
|
/// let id2 = arena.alloc(40);
|
||||||
|
/// let id3 = arena.alloc(60);
|
||||||
|
///
|
||||||
|
/// let mut iterator = arena.iter();
|
||||||
|
/// assert_eq!(iterator.next(), Some((id1, &20)));
|
||||||
|
/// assert_eq!(iterator.next(), Some((id2, &40)));
|
||||||
|
/// assert_eq!(iterator.next(), Some((id3, &60)));
|
||||||
|
/// ```
|
||||||
pub fn iter(
|
pub fn iter(
|
||||||
&self,
|
&self,
|
||||||
) -> impl Iterator<Item = (Idx<T>, &T)> + ExactSizeIterator + DoubleEndedIterator {
|
) -> impl Iterator<Item = (Idx<T>, &T)> + ExactSizeIterator + DoubleEndedIterator {
|
||||||
self.data.iter().enumerate().map(|(idx, value)| (Idx::from_raw(RawId(idx as u32)), value))
|
self.data.iter().enumerate().map(|(idx, value)| (Idx::from_raw(RawId(idx as u32)), value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reallocates the arena to make it take up as little space as possible.
|
||||||
pub fn shrink_to_fit(&mut self) {
|
pub fn shrink_to_fit(&mut self) {
|
||||||
self.data.shrink_to_fit();
|
self.data.shrink_to_fit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ pub struct ArenaMap<ID, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, V> ArenaMap<Idx<T>, V> {
|
impl<T, V> ArenaMap<Idx<T>, V> {
|
||||||
|
/// Inserts a value associated with a given arena ID into the map.
|
||||||
pub fn insert(&mut self, id: Idx<T>, t: V) {
|
pub fn insert(&mut self, id: Idx<T>, t: V) {
|
||||||
let idx = Self::to_idx(id);
|
let idx = Self::to_idx(id);
|
||||||
|
|
||||||
|
@ -19,22 +20,27 @@ impl<T, V> ArenaMap<Idx<T>, V> {
|
||||||
self.v[idx] = Some(t);
|
self.v[idx] = Some(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a reference to the value associated with the provided ID if it is present.
|
||||||
pub fn get(&self, id: Idx<T>) -> Option<&V> {
|
pub fn get(&self, id: Idx<T>) -> Option<&V> {
|
||||||
self.v.get(Self::to_idx(id)).and_then(|it| it.as_ref())
|
self.v.get(Self::to_idx(id)).and_then(|it| it.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable reference to the value associated with the provided ID if it is present.
|
||||||
pub fn get_mut(&mut self, id: Idx<T>) -> Option<&mut V> {
|
pub fn get_mut(&mut self, id: Idx<T>) -> Option<&mut V> {
|
||||||
self.v.get_mut(Self::to_idx(id)).and_then(|it| it.as_mut())
|
self.v.get_mut(Self::to_idx(id)).and_then(|it| it.as_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator over the values in the map.
|
||||||
pub fn values(&self) -> impl Iterator<Item = &V> {
|
pub fn values(&self) -> impl Iterator<Item = &V> {
|
||||||
self.v.iter().filter_map(|o| o.as_ref())
|
self.v.iter().filter_map(|o| o.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator over mutable references to the values in the map.
|
||||||
pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
|
pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
|
||||||
self.v.iter_mut().filter_map(|o| o.as_mut())
|
self.v.iter_mut().filter_map(|o| o.as_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator over the arena IDs and values in the map.
|
||||||
pub fn iter(&self) -> impl Iterator<Item = (Idx<T>, &V)> {
|
pub fn iter(&self) -> impl Iterator<Item = (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()?)))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue