use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::fmt;
use std::hash::BuildHasherDefault;
use crate::boxed::AnyCloneBox;
use crate::utils::IdHasher;
use crate::vec::{AnyVec, AnyVecMutRef};
#[repr(transparent)]
pub struct AnyMultiMap {
map: HashMap<TypeId, AnyVec, BuildHasherDefault<IdHasher>>,
}
impl Default for AnyMultiMap {
fn default() -> Self {
Self::new()
}
}
impl AnyMultiMap {
pub fn new() -> AnyMultiMap {
AnyMultiMap {
map: HashMap::default(),
}
}
pub fn type_count(&self) -> usize {
self.map.len()
}
pub fn len<T: Any + Send + Sync>(&self) -> usize {
self.map
.get(&TypeId::of::<T>())
.map(|vec| vec.len())
.unwrap_or(0)
}
pub fn len_total(&self) -> usize {
self.map.values().map(|vec| vec.len()).sum()
}
pub fn contains<T: Any + Send + Sync>(&self) -> bool {
self.map
.get(&TypeId::of::<T>())
.map(|vec| !vec.is_empty())
.unwrap_or(false)
}
pub fn contains_any(&self) -> bool {
self.map.values().any(|vec| !vec.is_empty())
}
pub fn is_empty<T: Any + Send + Sync>(&self) -> bool {
!self.contains::<T>()
}
pub fn is_completely_empty(&self) -> bool {
!self.contains_any()
}
pub fn clear<T: Any + Send + Sync>(&mut self) {
self.map.remove(&TypeId::of::<T>());
}
pub fn clear_all(&mut self) {
self.map.clear();
}
pub fn get<T: Any + Send + Sync>(&self) -> &[T] {
self.map
.get(&TypeId::of::<T>())
.map(|vec| {
debug_assert_eq!(
vec.elem_type_id(),
TypeId::of::<T>(),
"TypeId mismatch in AnyMultiMap::get. This should never happen!"
);
unsafe {
vec.get_unchecked()
}
})
.unwrap_or(&[])
}
pub fn get_mut<T: Any + Send + Sync>(&mut self) -> AnyVecMutRef<'_, T> {
let vec = self
.map
.entry(TypeId::of::<T>())
.or_insert_with(|| AnyVec::new::<T>());
debug_assert_eq!(
vec.elem_type_id(),
TypeId::of::<T>(),
"TypeId mismatch in AnyMultiMap::get_mut. This should never happen!"
);
unsafe {
vec.get_mut_unchecked()
}
}
pub fn insert<T: Any + Send + Sync>(&mut self, value: T) {
let mut vec = self.get_mut::<T>();
vec.push(value);
}
pub fn insert_boxed(&mut self, value: AnyCloneBox) {
value.insert_into_multimap(self);
}
}
struct TypeCount(usize);
impl fmt::Debug for TypeCount {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_fmt(format_args!("{} entries", self.0))
}
}
impl fmt::Debug for AnyMultiMap {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map()
.entries(
self.map
.values()
.map(|vec| (vec.type_name(), TypeCount(vec.len()))),
)
.finish()
}
}