use std::{any::TypeId, collections::HashSet};
use crate::ComponentKind;
#[derive(Clone, Default)]
pub struct ResourceKinds {
kinds: HashSet<ComponentKind>,
type_ids: HashSet<TypeId>,
}
impl ResourceKinds {
pub fn new() -> Self {
Self::default()
}
pub fn register<R: 'static>(&mut self, kind: ComponentKind) {
self.kinds.insert(kind);
self.type_ids.insert(TypeId::of::<R>());
}
pub fn is_resource(&self, kind: &ComponentKind) -> bool {
self.kinds.contains(kind)
}
pub fn kind_for<R: 'static>(&self) -> Option<ComponentKind> {
let kind = ComponentKind::from(TypeId::of::<R>());
if self.kinds.contains(&kind) {
Some(kind)
} else {
None
}
}
pub fn len(&self) -> usize {
self.kinds.len()
}
pub fn is_empty(&self) -> bool {
self.kinds.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &ComponentKind> {
self.kinds.iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn kind_from(name: &'static str) -> ComponentKind {
struct A;
struct B;
struct C;
match name {
"a" => ComponentKind::from(TypeId::of::<A>()),
"b" => ComponentKind::from(TypeId::of::<B>()),
_ => ComponentKind::from(TypeId::of::<C>()),
}
}
#[test]
fn unregistered_kind_is_not_resource() {
let rk = ResourceKinds::new();
assert!(!rk.is_resource(&kind_from("a")));
assert_eq!(rk.len(), 0);
}
#[test]
fn registered_kind_is_recognized() {
let mut rk = ResourceKinds::new();
let k = kind_from("a");
rk.kinds.insert(k);
rk.type_ids.insert(TypeId::of::<u8>());
assert!(rk.is_resource(&k));
assert!(!rk.is_resource(&kind_from("b")));
assert_eq!(rk.len(), 1);
}
}