2020-09-23 08:09:16 +02:00
|
|
|
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.
|
2020-09-23 23:32:11 -05:00
|
|
|
pub enum SsoHashSet<T> {
|
2020-09-23 08:09:16 +02:00
|
|
|
Array(ArrayVec<[T; 8]>),
|
|
|
|
Set(FxHashSet<T>),
|
|
|
|
}
|
|
|
|
|
2020-09-23 23:32:11 -05:00
|
|
|
impl<T: Eq + Hash> SsoHashSet<T> {
|
|
|
|
/// Creates an empty `SsoHashSet`.
|
2020-09-23 08:09:16 +02:00
|
|
|
pub fn new() -> Self {
|
2020-09-23 23:32:11 -05:00
|
|
|
SsoHashSet::Array(ArrayVec::new())
|
2020-09-23 08:09:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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 {
|
2020-09-23 23:32:11 -05:00
|
|
|
SsoHashSet::Array(array) => {
|
2020-09-23 08:09:16 +02:00
|
|
|
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());
|
2020-09-23 23:32:11 -05:00
|
|
|
*self = SsoHashSet::Set(set);
|
2020-09-23 08:09:16 +02:00
|
|
|
}
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
2020-09-23 23:32:11 -05:00
|
|
|
SsoHashSet::Set(set) => set.insert(elem),
|
2020-09-23 08:09:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|