mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-05 05:04:24 +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,8 +3,8 @@ name = "la-arena"
|
||||
version = "0.1.0"
|
||||
description = "Thy rope of sands..."
|
||||
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"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
@ -1,4 +1,6 @@
|
||||
//! Yet another index-based arena.
|
||||
//! Yet another ID-based arena.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use std::{
|
||||
fmt,
|
||||
@ -10,6 +12,7 @@ use std::{
|
||||
|
||||
pub mod map;
|
||||
|
||||
/// The raw ID of a value in an arena.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
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> {
|
||||
raw: RawId,
|
||||
_ty: PhantomData<fn() -> T>,
|
||||
@ -73,14 +77,18 @@ impl<T> fmt::Debug for Idx<T> {
|
||||
}
|
||||
|
||||
impl<T> Idx<T> {
|
||||
/// Creates a new ID from a [`RawId`].
|
||||
pub fn from_raw(raw: RawId) -> Self {
|
||||
Idx { raw, _ty: PhantomData }
|
||||
}
|
||||
|
||||
/// Converts this ID into the underlying [`RawId`].
|
||||
pub fn into_raw(self) -> RawId {
|
||||
self.raw
|
||||
}
|
||||
}
|
||||
|
||||
/// Yet another ID-based arena.
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct Arena<T> {
|
||||
data: Vec<T>,
|
||||
@ -93,29 +101,99 @@ impl<T: fmt::Debug> fmt::Debug for 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> {
|
||||
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) {
|
||||
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 {
|
||||
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 {
|
||||
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> {
|
||||
let id = RawId(self.data.len() as u32);
|
||||
self.data.push(value);
|
||||
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(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (Idx<T>, &T)> + ExactSizeIterator + DoubleEndedIterator {
|
||||
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) {
|
||||
self.data.shrink_to_fit();
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ pub struct ArenaMap<ID, 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) {
|
||||
let idx = Self::to_idx(id);
|
||||
|
||||
@ -19,22 +20,27 @@ impl<T, V> ArenaMap<Idx<T>, V> {
|
||||
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> {
|
||||
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> {
|
||||
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> {
|
||||
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> {
|
||||
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)> {
|
||||
self.v.iter().enumerate().filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?)))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user