use alloc::boxed::Box;
use core::any::TypeId;
use core::hash::{BuildHasher, Hash};
use indexmap::IndexMap;
use crate::{MaybeSend, MaybeSync};
pub(crate) type DynIndexMap<K, S> = Box<dyn AnyIndexMap<K, S>>;
trait Seal {}
impl<K, V: 'static, S> Seal for IndexMap<K, V, S> {}
#[expect(private_bounds)]
pub trait AnyIndexMap<K, S>: Seal + MaybeSend + MaybeSync {
fn value_type_id(&self) -> TypeId;
fn dyn_swap_remove(&mut self, key: &K) -> bool;
fn dyn_contains(&self, key: &K) -> bool;
}
impl<K, V, S> AnyIndexMap<K, S> for IndexMap<K, V, S>
where
K: Eq + Hash + 'static,
V: 'static,
S: BuildHasher,
Self: MaybeSend + MaybeSync,
{
fn value_type_id(&self) -> TypeId {
TypeId::of::<V>()
}
fn dyn_swap_remove(&mut self, key: &K) -> bool {
self.swap_remove(key).is_some()
}
fn dyn_contains(&self, key: &K) -> bool {
self.contains_key(key)
}
}
impl<K, S> dyn AnyIndexMap<K, S> {
#[inline]
pub fn value_is<V: 'static>(&self) -> bool {
self.value_type_id() == TypeId::of::<V>()
}
#[inline]
pub fn downcast_ref<V: 'static>(
&self,
) -> Option<&IndexMap<K, V, S>> {
if self.value_is::<V>() {
unsafe { Some(self.downcast_unchecked_ref()) }
} else {
None
}
}
#[inline]
pub fn downcast_mut<V: 'static>(
&mut self,
) -> Option<&mut IndexMap<K, V, S>> {
if self.value_is::<V>() {
unsafe { Some(self.downcast_unchecked_mut()) }
} else {
None
}
}
#[inline]
pub unsafe fn downcast_unchecked_ref<V: 'static>(
&self,
) -> &IndexMap<K, V, S> {
debug_assert!(self.value_is::<V>());
let ptr = self as *const Self as *const IndexMap<K, V, S>;
unsafe { &*ptr }
}
#[inline]
pub unsafe fn downcast_unchecked_mut<V: 'static>(
&mut self,
) -> &mut IndexMap<K, V, S> {
debug_assert!(self.value_is::<V>());
let ptr = self as *mut Self as *mut IndexMap<K, V, S>;
unsafe { &mut *ptr }
}
}