use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use crate::internal::{
conversion::{FromBindgen, IntoBindgen},
wit::{self},
};
use super::{
Component, ComponentIndex, ComponentValue, SupportedValue, SupportedValueRef, UntypedComponent,
};
#[derive(Clone, Default, Serialize, Deserialize, PartialEq)]
pub struct Entity(pub(crate) HashMap<ComponentIndex, ComponentValue>);
impl Entity {
pub fn new() -> Self {
Self::default()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn has<T: SupportedValue>(&self, component: Component<T>) -> bool {
self.0.contains_key(&component.index())
}
pub fn has_components(&self, components: &[&dyn UntypedComponent]) -> bool {
components
.iter()
.all(|component| self.0.contains_key(&component.index()))
}
pub fn get<T: SupportedValue>(&self, component: Component<T>) -> Option<T> {
T::from_value(self.0.get(&component.index())?.clone())
}
pub fn get_ref<T: SupportedValueRef>(&self, component: Component<T>) -> Option<&T> {
T::from_value_ref(self.0.get(&component.index())?)
}
pub fn set<T: SupportedValue>(&mut self, component: Component<T>, value: T) {
self.0.insert(component.index(), value.into_value());
}
pub fn set_default<T: SupportedValue + Default>(&mut self, component: Component<T>) {
self.set(component, T::default())
}
pub fn with<T: SupportedValue>(mut self, component: Component<T>, value: T) -> Self {
self.set(component, value);
self
}
pub fn with_merge(mut self, other: impl Into<Entity>) -> Self {
self.merge(other.into());
self
}
pub fn without<T: SupportedValue>(mut self, component: Component<T>) -> Self {
self.0.remove(&component.index());
self
}
pub fn remove<T: SupportedValue>(&mut self, component: Component<T>) -> Option<T> {
T::from_value(self.0.remove(&component.index())?)
}
pub fn merge(&mut self, other: Entity) {
self.0.extend(other.0);
}
pub fn spawn(&self) -> crate::prelude::EntityId {
crate::entity::spawn(self)
}
}
impl FromBindgen for wit::component::Entity {
type Item = Entity;
fn from_bindgen(self) -> Self::Item {
Entity(
self.into_iter()
.map(|(k, v)| (k, v.from_bindgen()))
.collect(),
)
}
}
impl IntoBindgen for Entity {
type Item = wit::component::Entity;
fn into_bindgen(self) -> Self::Item {
self.0
.into_iter()
.map(|(k, v)| (k, v.into_bindgen()))
.collect()
}
}
impl std::fmt::Debug for Entity {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_map()
.entries(self.0.iter().map(|(k, v)| {
(
wit::component::get_id(*k).unwrap_or_else(|| format!("unknown component {k}")),
v,
)
}))
.finish()
}
}