use std::borrow::Borrow; use std::cell::{Cell, UnsafeCell}; use std::collections::hash_map::RandomState; use std::collections::BTreeMap; use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; use std::iter::FromIterator; use std::ops::Index; use stable_deref_trait::StableDeref; /// Append-only version of `std::collections::HashMap` where /// insertion does not require mutable access pub struct FrozenMap { map: UnsafeCell>, /// Eq/Hash implementations can have side-effects, and using Rc it is possible /// for FrozenMap::insert to be called on a key that itself contains the same /// `FrozenMap`, whose `eq` implementation also calls FrozenMap::insert /// /// We use this `in_use` flag to guard against any reentrancy. in_use: Cell, } // safety: UnsafeCell implies !Sync impl FrozenMap { pub fn new() -> Self { Self { map: UnsafeCell::new(Default::default()), in_use: Cell::new(false), } } /// # Examples /// /// ``` /// use elsa::FrozenMap; /// /// let map = FrozenMap::new(); /// assert_eq!(map.len(), 0); /// map.insert(1, Box::new("a")); /// assert_eq!(map.len(), 1); /// ``` pub fn len(&self) -> usize { assert!(!self.in_use.get()); self.in_use.set(true); let len = unsafe { let map = self.map.get(); (*map).len() }; self.in_use.set(false); len } /// # Examples /// /// ``` /// use elsa::FrozenMap; /// /// let map = FrozenMap::new(); /// assert_eq!(map.is_empty(), true); /// map.insert(1, Box::new("a")); /// assert_eq!(map.is_empty(), false); /// ``` pub fn is_empty(&self) -> bool { self.len() == 0 } } impl FrozenMap { // these should never return &K or &V // these should never delete any entries pub fn insert(&self, k: K, v: V) -> &V::Target { assert!(!self.in_use.get()); self.in_use.set(true); let ret = unsafe { let map = self.map.get(); &*(*map).entry(k).or_insert(v) }; self.in_use.set(false); ret } /// Returns a reference to the value corresponding to the key. /// /// The key may be any borrowed form of the map's key type, but /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for /// the key type. /// /// # Examples /// /// ``` /// use elsa::FrozenMap; /// /// let map = FrozenMap::new(); /// map.insert(1, Box::new("a")); /// assert_eq!(map.get(&1), Some(&"a")); /// assert_eq!(map.get(&2), None); /// ``` pub fn get(&self, k: &Q) -> Option<&V::Target> where K: Borrow, Q: Hash + Eq, { assert!(!self.in_use.get()); self.in_use.set(true); let ret = unsafe { let map = self.map.get(); (*map).get(k).map(|x| &**x) }; self.in_use.set(false); ret } /// Applies a function to the owner of the value corresponding to the key (if any). /// /// The key may be any borrowed form of the map's key type, but /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for /// the key type. /// /// # Examples /// /// ``` /// use elsa::FrozenMap; /// /// let map = FrozenMap::new(); /// map.insert(1, Box::new("a")); /// assert_eq!(map.map_get(&1, Clone::clone), Some(Box::new("a"))); /// assert_eq!(map.map_get(&2, Clone::clone), None); /// ``` pub fn map_get(&self, k: &Q, f: F) -> Option where K: Borrow, Q: Hash + Eq, F: FnOnce(&V) -> T, { assert!(!self.in_use.get()); self.in_use.set(true); let ret = unsafe { let map = self.map.get(); (*map).get(k).map(f) }; self.in_use.set(false); ret } pub fn into_map(self) -> HashMap { self.map.into_inner() } // TODO add more } impl FrozenMap { /// Returns a reference to the key and value matching a borrowed /// key. /// /// The key argument may be any borrowed form of the map's key type, /// but [`Hash`] and [`Eq`] on the borrowed form *must* match those /// for the key type. /// /// # Examples /// /// ``` /// use elsa::FrozenMap; /// /// let map = FrozenMap::new(); /// map.insert(Box::new("1"), Box::new("a")); /// assert_eq!(map.get_key_value(&"1"), Some((&"1", &"a"))); /// assert_eq!(map.get_key_value(&"2"), None); /// ``` pub fn get_key_value(&self, k: &Q) -> Option<(&K::Target, &V::Target)> where K: Borrow, Q: Hash + Eq, { assert!(!self.in_use.get()); self.in_use.set(true); let ret = unsafe { let map = self.map.get(); (*map).get_key_value(k).map(|(k, v)| (&**k, &**v)) }; self.in_use.set(false); ret } } impl std::convert::AsMut> for FrozenMap { /// Get mutable access to the underlying [`HashMap`]. /// /// This is safe, as it requires a `&mut self`, ensuring nothing is using /// the 'frozen' contents. fn as_mut(&mut self) -> &mut HashMap { unsafe { &mut *self.map.get() } } } impl From> for FrozenMap { fn from(map: HashMap) -> Self { Self { map: UnsafeCell::new(map), in_use: Cell::new(false), } } } impl Index<&Q> for FrozenMap where Q: Eq + Hash, K: Eq + Hash + Borrow, V: StableDeref, S: BuildHasher, { type Output = V::Target; /// # Examples /// /// ``` /// use elsa::FrozenMap; /// /// let map = FrozenMap::new(); /// map.insert(1, Box::new("a")); /// assert_eq!(map[&1], "a"); /// ``` fn index(&self, idx: &Q) -> &V::Target { self.get(idx) .expect("attempted to index FrozenMap with unknown key") } } impl FromIterator<(K, V)> for FrozenMap { fn from_iter(iter: T) -> Self where T: IntoIterator, { let map: HashMap<_, _, _> = iter.into_iter().collect(); map.into() } } impl Default for FrozenMap { fn default() -> Self { Self { map: UnsafeCell::new(Default::default()), in_use: Cell::new(false), } } } /// Append-only version of `std::collections::BTreeMap` where /// insertion does not require mutable access pub struct FrozenBTreeMap { map: UnsafeCell>, /// Eq/Hash implementations can have side-effects, and using Rc it is possible /// for FrozenBTreeMap::insert to be called on a key that itself contains the same /// `FrozenBTreeMap`, whose `eq` implementation also calls FrozenBTreeMap::insert /// /// We use this `in_use` flag to guard against any reentrancy. in_use: Cell, } // safety: UnsafeCell implies !Sync impl FrozenBTreeMap { pub fn new() -> Self { Self { map: UnsafeCell::new(Default::default()), in_use: Cell::new(false), } } /// # Examples /// /// ``` /// use elsa::FrozenBTreeMap; /// /// let map = FrozenBTreeMap::new(); /// assert_eq!(map.len(), 0); /// map.insert(1, Box::new("a")); /// assert_eq!(map.len(), 1); /// ``` pub fn len(&self) -> usize { assert!(!self.in_use.get()); self.in_use.set(true); let len = unsafe { let map = self.map.get(); (*map).len() }; self.in_use.set(false); len } /// # Examples /// /// ``` /// use elsa::FrozenBTreeMap; /// /// let map = FrozenBTreeMap::new(); /// assert_eq!(map.is_empty(), true); /// map.insert(1, Box::new("a")); /// assert_eq!(map.is_empty(), false); /// ``` pub fn is_empty(&self) -> bool { self.len() == 0 } } impl FrozenBTreeMap { // these should never return &K or &V // these should never delete any entries pub fn insert(&self, k: K, v: V) -> &V::Target { assert!(!self.in_use.get()); self.in_use.set(true); let ret = unsafe { let map = self.map.get(); &*(*map).entry(k).or_insert(v) }; self.in_use.set(false); ret } /// Returns a reference to the value corresponding to the key. /// /// The key may be any borrowed form of the map's key type, but /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for /// the key type. /// /// # Examples /// /// ``` /// use elsa::FrozenBTreeMap; /// /// let map = FrozenBTreeMap::new(); /// map.insert(1, Box::new("a")); /// assert_eq!(map.get(&1), Some(&"a")); /// assert_eq!(map.get(&2), None); /// ``` pub fn get(&self, k: &Q) -> Option<&V::Target> where K: Borrow, Q: Ord, { assert!(!self.in_use.get()); self.in_use.set(true); let ret = unsafe { let map = self.map.get(); (*map).get(k).map(|x| &**x) }; self.in_use.set(false); ret } /// Applies a function to the owner of the value corresponding to the key (if any). /// /// The key may be any borrowed form of the map's key type, but /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for /// the key type. /// /// # Examples /// /// ``` /// use elsa::FrozenBTreeMap; /// /// let map = FrozenBTreeMap::new(); /// map.insert(1, Box::new("a")); /// assert_eq!(map.map_get(&1, Clone::clone), Some(Box::new("a"))); /// assert_eq!(map.map_get(&2, Clone::clone), None); /// ``` pub fn map_get(&self, k: &Q, f: F) -> Option where K: Borrow, Q: Ord, F: FnOnce(&V) -> T, { assert!(!self.in_use.get()); self.in_use.set(true); let ret = unsafe { let map = self.map.get(); (*map).get(k).map(f) }; self.in_use.set(false); ret } pub fn into_map(self) -> BTreeMap { self.map.into_inner() } // TODO add more } impl std::convert::AsMut> for FrozenBTreeMap { /// Get mutable access to the underlying [`HashMap`]. /// /// This is safe, as it requires a `&mut self`, ensuring nothing is using /// the 'frozen' contents. fn as_mut(&mut self) -> &mut BTreeMap { unsafe { &mut *self.map.get() } } } impl From> for FrozenBTreeMap { fn from(map: BTreeMap) -> Self { Self { map: UnsafeCell::new(map), in_use: Cell::new(false), } } } impl Index<&Q> for FrozenBTreeMap where Q: Ord, K: Clone + Ord + Borrow, V: StableDeref, { type Output = V::Target; /// # Examples /// /// ``` /// use elsa::FrozenBTreeMap; /// /// let map = FrozenBTreeMap::new(); /// map.insert(1, Box::new("a")); /// assert_eq!(map[&1], "a"); /// ``` fn index(&self, idx: &Q) -> &V::Target { self.get(idx) .expect("attempted to index FrozenBTreeMap with unknown key") } } impl FromIterator<(K, V)> for FrozenBTreeMap { fn from_iter(iter: T) -> Self where T: IntoIterator, { let map: BTreeMap<_, _> = iter.into_iter().collect(); map.into() } } impl Default for FrozenBTreeMap { fn default() -> Self { Self { map: UnsafeCell::new(Default::default()), in_use: Cell::new(false), } } }