use std::{
collections::{HashMap, HashSet},
fmt,
hash::{BuildHasher, Hash},
marker::PhantomData,
};
use crate::{IndexedSet, id::DenseIndex};
macro_rules! impl_dense_index_for_int {
($($ty:ty),* $(,)?) => {
$(
impl crate::id::DenseIndex for $ty {
fn from_index(index: usize) -> Self {
index.try_into().expect("solver id overflow")
}
fn to_index(self) -> usize {
self.try_into().expect("solver id does not fit in usize")
}
}
)*
};
}
impl_dense_index_for_int!(u16, u32, u64);
#[repr(transparent)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct DenseId<Tag, Repr: DenseIndex + Copy + Eq + Hash + fmt::Debug + 'static = u32> {
raw: Repr,
_marker: PhantomData<fn(Tag) -> Tag>,
}
impl<Tag, Repr: DenseIndex + Copy + Eq + Hash + fmt::Debug + 'static> DenseId<Tag, Repr> {
pub fn from_raw(raw: Repr) -> Self {
Self {
raw,
_marker: PhantomData,
}
}
pub fn into_raw(self) -> Repr {
self.raw
}
}
impl<Tag, Repr: DenseIndex + Copy + Eq + Hash + fmt::Debug + 'static> Copy for DenseId<Tag, Repr> {}
impl<Tag, Repr: DenseIndex + Copy + Eq + Hash + fmt::Debug + 'static> Clone for DenseId<Tag, Repr> {
fn clone(&self) -> Self {
*self
}
}
impl<Tag, Repr: DenseIndex + Copy + Eq + Hash + fmt::Debug + 'static> PartialEq
for DenseId<Tag, Repr>
{
fn eq(&self, other: &Self) -> bool {
self.raw == other.raw
}
}
impl<Tag, Repr: DenseIndex + Copy + Eq + Hash + fmt::Debug + 'static> Eq for DenseId<Tag, Repr> {}
impl<Tag, Repr: DenseIndex + Copy + Eq + Hash + fmt::Debug + 'static> Hash for DenseId<Tag, Repr> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.raw.hash(state);
}
}
impl<Tag, Repr: DenseIndex + Copy + Eq + Hash + fmt::Debug + 'static> fmt::Debug
for DenseId<Tag, Repr>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.raw.fmt(f)
}
}
impl<Tag, Repr: DenseIndex + Copy + Eq + Hash + fmt::Debug + 'static + Ord> Ord
for DenseId<Tag, Repr>
{
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.raw.cmp(&other.raw)
}
}
impl<Tag, Repr: DenseIndex + Copy + Eq + Hash + fmt::Debug + 'static + Ord> PartialOrd
for DenseId<Tag, Repr>
{
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<Tag, Repr: DenseIndex + Copy + Eq + Hash + fmt::Debug + 'static> DenseIndex
for DenseId<Tag, Repr>
{
fn from_index(x: usize) -> Self {
Self::from_raw(Repr::from_index(x))
}
fn to_index(self) -> usize {
self.raw.to_index()
}
}
impl<Tag, Repr: DenseIndex + Copy + Eq + Hash + fmt::Debug + 'static> SolverId
for DenseId<Tag, Repr>
{
type Map<V: Copy + Default> = Vec<V>;
type Set = IndexedSet<Self>;
}
#[repr(transparent)]
pub struct SparseId<
Tag,
Repr: Copy + Eq + Hash + fmt::Debug + 'static = u32,
H = ahash::RandomState,
> {
raw: Repr,
_marker: PhantomData<fn(Tag, H) -> Tag>,
}
impl<Tag, Repr: Copy + Eq + Hash + fmt::Debug + 'static, H> SparseId<Tag, Repr, H> {
pub fn from_raw(raw: Repr) -> Self {
Self {
raw,
_marker: PhantomData,
}
}
pub fn into_raw(self) -> Repr {
self.raw
}
}
impl<Tag, Repr: Copy + Eq + Hash + fmt::Debug + 'static, H> Copy for SparseId<Tag, Repr, H> {}
impl<Tag, Repr: Copy + Eq + Hash + fmt::Debug + 'static, H> Clone for SparseId<Tag, Repr, H> {
fn clone(&self) -> Self {
*self
}
}
impl<Tag, Repr: Copy + Eq + Hash + fmt::Debug + 'static, H> PartialEq for SparseId<Tag, Repr, H> {
fn eq(&self, other: &Self) -> bool {
self.raw == other.raw
}
}
impl<Tag, Repr: Copy + Eq + Hash + fmt::Debug + 'static, H> Eq for SparseId<Tag, Repr, H> {}
impl<Tag, Repr: Copy + Eq + Hash + fmt::Debug + 'static, H> Hash for SparseId<Tag, Repr, H> {
fn hash<HA: std::hash::Hasher>(&self, state: &mut HA) {
self.raw.hash(state);
}
}
impl<Tag, Repr: Copy + Eq + Hash + fmt::Debug + 'static, H> fmt::Debug for SparseId<Tag, Repr, H> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.raw.fmt(f)
}
}
impl<Tag, Repr: Copy + Eq + Hash + fmt::Debug + 'static, H: Default + BuildHasher> SolverId
for SparseId<Tag, Repr, H>
{
type Map<V: Copy + Default> = HashMap<Self, V, H>;
type Set = HashSet<Self, H>;
}
pub trait IdMap<K, V: Copy + Default> {
fn get(&self, key: K) -> V;
fn set(&mut self, key: K, value: V);
fn for_each_mut(&mut self, visit: impl FnMut(&mut V));
fn for_each(&self, visit: impl FnMut(&V));
}
pub trait IdSet<K> {
fn contains(&self, key: K) -> bool;
fn insert(&mut self, key: K) -> bool;
}
pub trait SolverId: Copy + Eq + Hash + std::fmt::Debug {
type Map<V: Copy + Default>: IdMap<Self, V> + Default;
type Set: IdSet<Self> + Default;
}
impl<K: DenseIndex, V: Copy + Default> IdMap<K, V> for Vec<V> {
fn get(&self, key: K) -> V {
self.as_slice()
.get(key.to_index())
.copied()
.unwrap_or_default()
}
fn set(&mut self, key: K, value: V) {
let idx = key.to_index();
if idx >= self.len() {
self.resize(idx + 1, V::default());
}
self[idx] = value;
}
fn for_each_mut(&mut self, visit: impl FnMut(&mut V)) {
self.iter_mut().for_each(visit);
}
fn for_each(&self, visit: impl FnMut(&V)) {
self.iter().for_each(visit);
}
}
impl<K: DenseIndex> IdSet<K> for IndexedSet<K> {
fn contains(&self, key: K) -> bool {
IndexedSet::contains(self, key)
}
fn insert(&mut self, key: K) -> bool {
IndexedSet::insert(self, key)
}
}
impl<K: Eq + Hash, V: Copy + Default, S: BuildHasher> IdMap<K, V> for HashMap<K, V, S> {
fn get(&self, key: K) -> V {
HashMap::get(self, &key).copied().unwrap_or_default()
}
fn set(&mut self, key: K, value: V) {
HashMap::insert(self, key, value);
}
fn for_each_mut(&mut self, visit: impl FnMut(&mut V)) {
HashMap::values_mut(self).for_each(visit);
}
fn for_each(&self, visit: impl FnMut(&V)) {
HashMap::values(self).for_each(visit);
}
}
impl<K: Eq + Hash, H: BuildHasher> IdSet<K> for HashSet<K, H> {
fn contains(&self, key: K) -> bool {
HashSet::contains(self, &key)
}
fn insert(&mut self, key: K) -> bool {
HashSet::insert(self, key)
}
}