use serde::{Deserialize, Serialize};
use crate::Result;
use crate::entity::{EntityId, Summary};
pub trait HasName {
fn name(&self) -> &str;
}
pub trait StateEntity: HasName + Clone + Serialize + for<'de> Deserialize<'de> {
type Entry: Copy + core::fmt::Debug + AsRef<str>;
const STATE_ENTRY: Self::Entry;
fn description(&self) -> Option<&str> { None }
fn summary(&self, id: EntityId) -> Summary {
Summary {
id,
name: self.name().to_string(),
description: self.description().map(ToString::to_string),
}
}
}
pub trait StateCollection {
type Entity: StateEntity;
const STATE_ENTRY: <Self::Entity as StateEntity>::Entry;
fn load<I>(entities: I) -> Self
where
I: IntoIterator<Item = (EntityId, Self::Entity)>;
fn get_entity(&self, id: &str) -> Option<(&EntityId, &Self::Entity)>;
fn get_entities(&self) -> Vec<(&EntityId, &Self::Entity)>;
fn search_entities(&self, needle: &str) -> Vec<(&EntityId, &Self::Entity)>;
fn create(&mut self, entity: Self::Entity) -> EntityId;
fn update(&mut self, id: &str, entity: Self::Entity) -> Result<()>;
fn remove(&mut self, id: &str) -> Result<Self::Entity>;
fn list(&self) -> Vec<Summary>;
fn is_empty(&self) -> bool;
}
impl<T: StateCollection> StateCollection for Box<T> {
type Entity = T::Entity;
const STATE_ENTRY: <T::Entity as StateEntity>::Entry = T::STATE_ENTRY;
fn load<I>(entities: I) -> Self
where
I: IntoIterator<Item = (EntityId, Self::Entity)>,
{
Box::new(T::load(entities))
}
fn get_entity(&self, id: &str) -> Option<(&EntityId, &Self::Entity)> {
self.as_ref().get_entity(id)
}
fn get_entities(&self) -> Vec<(&EntityId, &Self::Entity)> { self.as_ref().get_entities() }
fn search_entities(&self, needle: &str) -> Vec<(&EntityId, &Self::Entity)> {
self.as_ref().search_entities(needle)
}
fn create(&mut self, entity: Self::Entity) -> EntityId { self.as_mut().create(entity) }
fn update(&mut self, id: &str, entity: Self::Entity) -> Result<()> {
self.as_mut().update(id, entity)
}
fn remove(&mut self, id: &str) -> Result<Self::Entity> { self.as_mut().remove(id) }
fn list(&self) -> Vec<Summary> { self.as_ref().list() }
fn is_empty(&self) -> bool { self.as_ref().is_empty() }
}