use std::{
any::type_name,
ops::{Index, IndexMut},
};
use hashbrown::HashMap;
use super::entity::Ent;
#[derive(Debug, Clone)]
pub struct Entry<T> {
pub id: Ent,
pub value: T,
}
#[derive(Debug)]
pub struct Component<T> {
id_to_index: HashMap<Ent, usize>,
store: Vec<Entry<T>>,
}
impl<T> Default for Component<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> Index<Ent> for Component<T> {
type Output = T;
fn index(&self, index: Ent) -> &Self::Output {
self.get(index).expect("component not found")
}
}
impl<T> IndexMut<Ent> for Component<T> {
fn index_mut(&mut self, index: Ent) -> &mut Self::Output {
self.get_mut(index).expect("component not found")
}
}
impl<T> Component<T> {
pub fn new() -> Self {
Self {
id_to_index: HashMap::new(),
store: Vec::new(),
}
}
pub fn get(&self, id: Ent) -> Option<&T> {
let index = self.id_to_index.get(&id)?;
let entry = self.store.get(*index)?;
Some(&entry.value)
}
pub fn get_mut(&mut self, id: Ent) -> Option<&mut T> {
let index = self.id_to_index.get(&id)?;
let entry = self.store.get_mut(*index)?;
Some(&mut entry.value)
}
pub fn add(&mut self, id: Ent, data: T) {
let index = self.store.len();
let existed = self.id_to_index.insert(id, index);
assert!(
existed.is_none(),
"component {:?}@{} already exists",
id,
type_name::<T>()
);
let entry = Entry { id, value: data };
self.store.push(entry);
}
pub fn remove(&mut self, id: Ent) -> Option<T> {
let index = self.id_to_index.remove(&id)?;
let entry = self.store.swap_remove(index);
if let Some(dirty) = self.store.get(index) {
self.id_to_index.insert(dirty.id, index);
}
Some(entry.value)
}
pub fn iter(&self) -> impl Iterator<Item = &Entry<T>> {
self.store.iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Entry<T>> {
self.store.iter_mut()
}
pub fn len(&self) -> usize {
self.store.len()
}
pub fn is_empty(&self) -> bool {
self.store.is_empty()
}
pub fn contains(&self, id: Ent) -> bool {
self.id_to_index.contains_key(&id)
}
}