use crate::{
db::EntityKey,
error::InternalError,
model::EntityModel,
traits::{AuthoredFieldProjection, CanisterKind, FieldProjection, StoreKind, TypeKind},
types::{EntityTag, Id},
};
pub trait EntityDeclaration: EntityKey {
const NAME: &'static str;
const MODEL: &'static EntityModel;
}
pub trait EntityPlacement {
type Store: StoreKind<Canister = Self::Canister>;
type Canister: CanisterKind;
}
pub trait EntityKind: EntityDeclaration + EntityPlacement + TypeKind {
const ENTITY_TAG: EntityTag;
}
pub trait EntityValue: EntityKey + AuthoredFieldProjection + FieldProjection + Sized {
fn id(&self) -> Id<Self>;
}
pub struct EntityCreateMaterialization<E> {
entity: E,
authored_slots: Vec<usize>,
}
impl<E> EntityCreateMaterialization<E> {
#[must_use]
pub const fn new(entity: E, authored_slots: Vec<usize>) -> Self {
Self {
entity,
authored_slots,
}
}
#[must_use]
pub fn into_entity(self) -> E {
self.entity
}
#[must_use]
pub const fn authored_slots(&self) -> &[usize] {
self.authored_slots.as_slice()
}
}
pub trait EntityCreateInput: Sized {
type Entity: EntityValue;
fn materialize_create(self)
-> Result<EntityCreateMaterialization<Self::Entity>, InternalError>;
}
pub trait EntityCreateType: EntityValue {
type Create: EntityCreateInput<Entity = Self>;
}
mod singleton {
pub trait Key {}
impl Key for () {}
impl Key for crate::types::Unit {}
pub trait Sealed {}
impl<E> Sealed for E
where
E: super::EntityValue,
E::Key: Key,
{
}
}
pub trait SingletonEntity: EntityValue + singleton::Sealed {}
impl<E> SingletonEntity for E where E: EntityValue + singleton::Sealed {}