about summary refs log tree commit diff
path: root/compiler/rustc_data_structures/src/sso
diff options
context:
space:
mode:
authorValerii Lashmanov <vflashm@gmail.com>2020-09-23 23:32:11 -0500
committerValerii Lashmanov <vflashm@gmail.com>2020-09-26 14:30:05 -0500
commit5c224a484dc6ba2a70c9cd0d73a04849f6d7aa68 (patch)
tree16919ad7dbdbb6ba195ac59da944d37d93bb6c18 /compiler/rustc_data_structures/src/sso
parent6f9a8a7f9b9732c55511d2a2a3914e8feafc7c52 (diff)
MiniSet/MiniMap moved and renamed into SsoHashSet/SsoHashMap
It is a more descriptive name and with upcoming changes
there will be nothing "mini" about them.
Diffstat (limited to 'compiler/rustc_data_structures/src/sso')
-rw-r--r--compiler/rustc_data_structures/src/sso/map.rs61
-rw-r--r--compiler/rustc_data_structures/src/sso/mod.rs5
-rw-r--r--compiler/rustc_data_structures/src/sso/set.rs41
3 files changed, 107 insertions, 0 deletions
diff --git a/compiler/rustc_data_structures/src/sso/map.rs b/compiler/rustc_data_structures/src/sso/map.rs
new file mode 100644
index 00000000000..c253e9d6616
--- /dev/null
+++ b/compiler/rustc_data_structures/src/sso/map.rs
@@ -0,0 +1,61 @@
+use crate::fx::FxHashMap;
+use arrayvec::ArrayVec;
+
+use std::hash::Hash;
+
+/// Small-storage-optimized implementation of a map
+/// made specifically for caching results.
+///
+/// Stores elements in a small array up to a certain length
+/// and switches to `HashMap` when that length is exceeded.
+pub enum SsoHashMap<K, V> {
+    Array(ArrayVec<[(K, V); 8]>),
+    Map(FxHashMap<K, V>),
+}
+
+impl<K: Eq + Hash, V> SsoHashMap<K, V> {
+    /// Creates an empty `SsoHashMap`.
+    pub fn new() -> Self {
+        SsoHashMap::Array(ArrayVec::new())
+    }
+
+    /// Inserts or updates value in the map.
+    pub fn insert(&mut self, key: K, value: V) {
+        match self {
+            SsoHashMap::Array(array) => {
+                for pair in array.iter_mut() {
+                    if pair.0 == key {
+                        pair.1 = value;
+                        return;
+                    }
+                }
+                if let Err(error) = array.try_push((key, value)) {
+                    let mut map: FxHashMap<K, V> = array.drain(..).collect();
+                    let (key, value) = error.element();
+                    map.insert(key, value);
+                    *self = SsoHashMap::Map(map);
+                }
+            }
+            SsoHashMap::Map(map) => {
+                map.insert(key, value);
+            }
+        }
+    }
+
+    /// Return value by key if any.
+    pub fn get(&self, key: &K) -> Option<&V> {
+        match self {
+            SsoHashMap::Array(array) => {
+                for pair in array {
+                    if pair.0 == *key {
+                        return Some(&pair.1);
+                    }
+                }
+                return None;
+            }
+            SsoHashMap::Map(map) => {
+                return map.get(key);
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_data_structures/src/sso/mod.rs b/compiler/rustc_data_structures/src/sso/mod.rs
new file mode 100644
index 00000000000..ef634b9adce
--- /dev/null
+++ b/compiler/rustc_data_structures/src/sso/mod.rs
@@ -0,0 +1,5 @@
+mod map;
+mod set;
+
+pub use map::SsoHashMap;
+pub use set::SsoHashSet;
diff --git a/compiler/rustc_data_structures/src/sso/set.rs b/compiler/rustc_data_structures/src/sso/set.rs
new file mode 100644
index 00000000000..b403c9dcc33
--- /dev/null
+++ b/compiler/rustc_data_structures/src/sso/set.rs
@@ -0,0 +1,41 @@
+use crate::fx::FxHashSet;
+use arrayvec::ArrayVec;
+use std::hash::Hash;
+/// Small-storage-optimized implementation of a set.
+///
+/// Stores elements in a small array up to a certain length
+/// and switches to `HashSet` when that length is exceeded.
+pub enum SsoHashSet<T> {
+    Array(ArrayVec<[T; 8]>),
+    Set(FxHashSet<T>),
+}
+
+impl<T: Eq + Hash> SsoHashSet<T> {
+    /// Creates an empty `SsoHashSet`.
+    pub fn new() -> Self {
+        SsoHashSet::Array(ArrayVec::new())
+    }
+
+    /// Adds a value to the set.
+    ///
+    /// If the set did not have this value present, true is returned.
+    ///
+    /// If the set did have this value present, false is returned.
+    pub fn insert(&mut self, elem: T) -> bool {
+        match self {
+            SsoHashSet::Array(array) => {
+                if array.iter().any(|e| *e == elem) {
+                    false
+                } else {
+                    if let Err(error) = array.try_push(elem) {
+                        let mut set: FxHashSet<T> = array.drain(..).collect();
+                        set.insert(error.element());
+                        *self = SsoHashSet::Set(set);
+                    }
+                    true
+                }
+            }
+            SsoHashSet::Set(set) => set.insert(elem),
+        }
+    }
+}