use std::cell::{Cell, UnsafeCell};
use std::collections::hash_map::RandomState;
use std::hash::{BuildHasher, Hash};
use std::iter::FromIterator;
use std::ops::Index;
use indexmap::IndexSet;
use stable_deref_trait::StableDeref;
use crate::index_map::Equivalent;
pub struct FrozenIndexSet<T, S = RandomState> {
set: UnsafeCell<IndexSet<T, S>>,
in_use: Cell<bool>,
}
impl<T: Eq + Hash> FrozenIndexSet<T> {
pub fn new() -> Self {
Self::from(IndexSet::new())
}
}
impl<T: Eq + Hash + StableDeref, S: BuildHasher> FrozenIndexSet<T, S> {
pub fn insert(&self, value: T) -> &T::Target {
assert!(!self.in_use.get());
self.in_use.set(true);
let ret = unsafe {
let set = self.set.get();
let (index, _was_vacant) = (*set).insert_full(value);
&*(*set)[index]
};
self.in_use.set(false);
ret
}
pub fn insert_full(&self, value: T) -> (usize, &T::Target) {
assert!(!self.in_use.get());
self.in_use.set(true);
let ret = unsafe {
let set = self.set.get();
let (index, _was_vacant) = (*set).insert_full(value);
(index, &*(*set)[index])
};
self.in_use.set(false);
ret
}
pub fn get<Q>(&self, k: &Q) -> Option<&T::Target>
where
Q: ?Sized + Hash + Equivalent<T>,
{
assert!(!self.in_use.get());
self.in_use.set(true);
let ret = unsafe {
let set = self.set.get();
(*set).get(k).map(|x| &**x)
};
self.in_use.set(false);
ret
}
pub fn get_index_of<Q>(&self, k: &Q) -> Option<usize>
where
Q: ?Sized + Hash + Equivalent<T>,
{
assert!(!self.in_use.get());
self.in_use.set(true);
let ret = unsafe {
let set = self.set.get();
(*set).get_index_of(k)
};
self.in_use.set(false);
ret
}
pub fn get_full<Q>(&self, k: &Q) -> Option<(usize, &T::Target)>
where
Q: ?Sized + Hash + Equivalent<T>,
{
assert!(!self.in_use.get());
self.in_use.set(true);
let ret = unsafe {
let set = self.set.get();
(*set).get_full(k).map(|(i, x)| (i, &**x))
};
self.in_use.set(false);
ret
}
pub fn get_index(&self, index: usize) -> Option<&T::Target> {
assert!(!self.in_use.get());
self.in_use.set(true);
let ret = unsafe {
let set = self.set.get();
(*set).get_index(index).map(|r| &**r)
};
self.in_use.set(false);
ret
}
}
impl<T, S> FrozenIndexSet<T, S> {
pub fn into_set(self) -> IndexSet<T, S> {
self.set.into_inner()
}
pub fn as_mut(&mut self) -> &mut IndexSet<T, S> {
unsafe { &mut *self.set.get() }
}
}
impl<T, S> From<IndexSet<T, S>> for FrozenIndexSet<T, S> {
fn from(set: IndexSet<T, S>) -> Self {
Self {
set: UnsafeCell::new(set),
in_use: Cell::new(false),
}
}
}
impl<T: Eq + Hash + StableDeref, S> Index<usize> for FrozenIndexSet<T, S> {
type Output = T::Target;
fn index(&self, idx: usize) -> &T::Target {
assert!(!self.in_use.get());
self.in_use.set(true);
let ret = unsafe {
let set = self.set.get();
&*(*set)[idx]
};
self.in_use.set(false);
ret
}
}
impl<T: Eq + Hash, S: Default + BuildHasher> FromIterator<T> for FrozenIndexSet<T, S> {
fn from_iter<U>(iter: U) -> Self
where
U: IntoIterator<Item = T>,
{
let set: IndexSet<_, _> = iter.into_iter().collect();
set.into()
}
}
impl<T: Eq + Hash, S: Default> Default for FrozenIndexSet<T, S> {
fn default() -> Self {
Self::from(IndexSet::default())
}
}
impl<K: Clone, V: Clone> Clone for FrozenIndexSet<K, V> {
fn clone(&self) -> Self {
assert!(!self.in_use.get());
self.in_use.set(true);
let self_clone = Self {
set: unsafe { self.set.get().as_ref().unwrap() }.clone().into(),
in_use: Cell::from(false),
};
self.in_use.set(false);
return self_clone;
}
}
impl<T: Hash + Eq, S: BuildHasher> PartialEq for FrozenIndexSet<T, S> {
fn eq(&self, other: &Self) -> bool {
assert!(!self.in_use.get());
assert!(!other.in_use.get());
self.in_use.set(true);
other.in_use.set(true);
let ret = unsafe { self.set.get().as_ref() == other.set.get().as_ref() };
self.in_use.set(false);
other.in_use.set(false);
ret
}
}