From 71f7d82e45145281b9aec5bcdc694524864e552b Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 6 Jan 2019 23:57:39 +0100 Subject: Introduce ArenaMap --- crates/ra_arena/src/lib.rs | 2 ++ crates/ra_arena/src/map.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 crates/ra_arena/src/map.rs (limited to 'crates/ra_arena/src') diff --git a/crates/ra_arena/src/lib.rs b/crates/ra_arena/src/lib.rs index a5eeb4118..040977dc4 100644 --- a/crates/ra_arena/src/lib.rs +++ b/crates/ra_arena/src/lib.rs @@ -6,6 +6,8 @@ use std::{ ops::{Index, IndexMut}, }; +pub mod map; + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct RawId(u32); diff --git a/crates/ra_arena/src/map.rs b/crates/ra_arena/src/map.rs new file mode 100644 index 000000000..2f09d677f --- /dev/null +++ b/crates/ra_arena/src/map.rs @@ -0,0 +1,70 @@ +//! A map from arena IDs to some other type. Space requirement is O(highest ID). + +use std::marker::PhantomData; + +use super::ArenaId; + +/// 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 { + v: Vec>, + _ty: PhantomData, +} + +impl ArenaMap { + pub fn insert(&mut self, id: ID, t: T) { + let idx = Self::to_idx(id); + if self.v.capacity() <= idx { + self.v.reserve(idx + 1 - self.v.capacity()); + } + if self.v.len() <= idx { + while self.v.len() <= idx { + self.v.push(None); + } + } + self.v[idx] = Some(t); + } + + pub fn get(&self, id: ID) -> Option<&T> { + self.v.get(Self::to_idx(id)).and_then(|it| it.as_ref()) + } + + pub fn values(&self) -> impl Iterator { + self.v.iter().filter_map(|o| o.as_ref()) + } + + pub fn values_mut(&mut self) -> impl Iterator { + self.v.iter_mut().filter_map(|o| o.as_mut()) + } + + pub fn iter(&self) -> impl Iterator { + self.v + .iter() + .enumerate() + .filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?))) + } + + fn to_idx(id: ID) -> usize { + u32::from(id.into_raw()) as usize + } + + fn from_idx(idx: usize) -> ID { + ID::from_raw((idx as u32).into()) + } +} + +impl std::ops::Index for ArenaMap { + type Output = T; + fn index(&self, id: ID) -> &T { + self.v[Self::to_idx(id)].as_ref().unwrap() + } +} + +impl Default for ArenaMap { + fn default() -> Self { + ArenaMap { + v: Vec::new(), + _ty: PhantomData, + } + } +} -- cgit v1.2.3