about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorAleksey Kladov <aleksey.kladov@gmail.com>2021-01-14 18:47:42 +0300
committerAleksey Kladov <aleksey.kladov@gmail.com>2021-01-14 19:06:02 +0300
commit4c4e54ac8a9782439744fe15aa31a3bedab92b74 (patch)
tree6f1653b0d60298cd2932fe7c3ba4cc802f7e8b14 /lib
parentaeacaeed4e49dd71ba0de30a21d9f3d1cc153cec (diff)
downloadrust-4c4e54ac8a9782439744fe15aa31a3bedab92b74.tar.gz
rust-4c4e54ac8a9782439744fe15aa31a3bedab92b74.zip
prepare to publish el libro de arena
Diffstat (limited to 'lib')
-rw-r--r--lib/README.md2
-rw-r--r--lib/arena/Cargo.toml10
-rw-r--r--lib/arena/src/lib.rs152
-rw-r--r--lib/arena/src/map.rs62
4 files changed, 226 insertions, 0 deletions
diff --git a/lib/README.md b/lib/README.md
new file mode 100644
index 00000000000..6b2eeac2c0d
--- /dev/null
+++ b/lib/README.md
@@ -0,0 +1,2 @@
+Crates in this directory are published to crates.io and obey semver.
+They *could* live in a separate repo, but we want to experiment with a monorepo setup.
diff --git a/lib/arena/Cargo.toml b/lib/arena/Cargo.toml
new file mode 100644
index 00000000000..183a5bb6a9a
--- /dev/null
+++ b/lib/arena/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "la-arena"
+version = "0.1.0"
+description = "Thy rope of sands..."
+license = "MIT OR Apache-2.0"
+authors = ["rust-analyzer developers"]
+edition = "2018"
+
+[lib]
+doctest = false
diff --git a/lib/arena/src/lib.rs b/lib/arena/src/lib.rs
new file mode 100644
index 00000000000..3169aa5b8cc
--- /dev/null
+++ b/lib/arena/src/lib.rs
@@ -0,0 +1,152 @@
+//! Yet another index-based arena.
+
+use std::{
+    fmt,
+    hash::{Hash, Hasher},
+    iter::FromIterator,
+    marker::PhantomData,
+    ops::{Index, IndexMut},
+};
+
+pub mod map;
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct RawId(u32);
+
+impl From<RawId> for u32 {
+    fn from(raw: RawId) -> u32 {
+        raw.0
+    }
+}
+
+impl From<u32> for RawId {
+    fn from(id: u32) -> RawId {
+        RawId(id)
+    }
+}
+
+impl fmt::Debug for RawId {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+impl fmt::Display for RawId {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+pub struct Idx<T> {
+    raw: RawId,
+    _ty: PhantomData<fn() -> T>,
+}
+
+impl<T> Clone for Idx<T> {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+impl<T> Copy for Idx<T> {}
+
+impl<T> PartialEq for Idx<T> {
+    fn eq(&self, other: &Idx<T>) -> bool {
+        self.raw == other.raw
+    }
+}
+impl<T> Eq for Idx<T> {}
+
+impl<T> Hash for Idx<T> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.raw.hash(state)
+    }
+}
+
+impl<T> fmt::Debug for Idx<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut type_name = std::any::type_name::<T>();
+        if let Some(idx) = type_name.rfind(':') {
+            type_name = &type_name[idx + 1..]
+        }
+        write!(f, "Idx::<{}>({})", type_name, self.raw)
+    }
+}
+
+impl<T> Idx<T> {
+    pub fn from_raw(raw: RawId) -> Self {
+        Idx { raw, _ty: PhantomData }
+    }
+    pub fn into_raw(self) -> RawId {
+        self.raw
+    }
+}
+
+#[derive(Clone, PartialEq, Eq)]
+pub struct Arena<T> {
+    data: Vec<T>,
+}
+
+impl<T: fmt::Debug> fmt::Debug for Arena<T> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        fmt.debug_struct("Arena").field("len", &self.len()).field("data", &self.data).finish()
+    }
+}
+
+impl<T> Arena<T> {
+    pub const fn new() -> Arena<T> {
+        Arena { data: Vec::new() }
+    }
+    pub fn clear(&mut self) {
+        self.data.clear();
+    }
+
+    pub fn len(&self) -> usize {
+        self.data.len()
+    }
+    pub fn is_empty(&self) -> bool {
+        self.data.is_empty()
+    }
+    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)
+    }
+    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))
+    }
+    pub fn shrink_to_fit(&mut self) {
+        self.data.shrink_to_fit();
+    }
+}
+
+impl<T> Default for Arena<T> {
+    fn default() -> Arena<T> {
+        Arena { data: Vec::new() }
+    }
+}
+
+impl<T> Index<Idx<T>> for Arena<T> {
+    type Output = T;
+    fn index(&self, idx: Idx<T>) -> &T {
+        let idx = idx.into_raw().0 as usize;
+        &self.data[idx]
+    }
+}
+
+impl<T> IndexMut<Idx<T>> for Arena<T> {
+    fn index_mut(&mut self, idx: Idx<T>) -> &mut T {
+        let idx = idx.into_raw().0 as usize;
+        &mut self.data[idx]
+    }
+}
+
+impl<T> FromIterator<T> for Arena<T> {
+    fn from_iter<I>(iter: I) -> Self
+    where
+        I: IntoIterator<Item = T>,
+    {
+        Arena { data: Vec::from_iter(iter) }
+    }
+}
diff --git a/lib/arena/src/map.rs b/lib/arena/src/map.rs
new file mode 100644
index 00000000000..0f33907c0ae
--- /dev/null
+++ b/lib/arena/src/map.rs
@@ -0,0 +1,62 @@
+//! A map from arena IDs to some other type. Space requirement is O(highest ID).
+
+use std::marker::PhantomData;
+
+use crate::Idx;
+
+/// A map from arena IDs to some other type. Space requirement is O(highest ID).
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct ArenaMap<ID, V> {
+    v: Vec<Option<V>>,
+    _ty: PhantomData<ID>,
+}
+
+impl<T, V> ArenaMap<Idx<T>, V> {
+    pub fn insert(&mut self, id: Idx<T>, t: V) {
+        let idx = Self::to_idx(id);
+
+        self.v.resize_with((idx + 1).max(self.v.len()), || None);
+        self.v[idx] = Some(t);
+    }
+
+    pub fn get(&self, id: Idx<T>) -> Option<&V> {
+        self.v.get(Self::to_idx(id)).and_then(|it| it.as_ref())
+    }
+
+    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())
+    }
+
+    pub fn values(&self) -> impl Iterator<Item = &V> {
+        self.v.iter().filter_map(|o| o.as_ref())
+    }
+
+    pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
+        self.v.iter_mut().filter_map(|o| o.as_mut())
+    }
+
+    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()?)))
+    }
+
+    fn to_idx(id: Idx<T>) -> usize {
+        u32::from(id.into_raw()) as usize
+    }
+
+    fn from_idx(idx: usize) -> Idx<T> {
+        Idx::from_raw((idx as u32).into())
+    }
+}
+
+impl<T, V> std::ops::Index<Idx<V>> for ArenaMap<Idx<V>, T> {
+    type Output = T;
+    fn index(&self, id: Idx<V>) -> &T {
+        self.v[Self::to_idx(id)].as_ref().unwrap()
+    }
+}
+
+impl<T, V> Default for ArenaMap<Idx<V>, T> {
+    fn default() -> Self {
+        ArenaMap { v: Vec::new(), _ty: PhantomData }
+    }
+}