mod numeric_value;
use crate::{
db::EntityKey,
error::InternalError,
model::field::{FieldKind, FieldModel, FieldStorageDecode},
prelude::*,
types::{EntityTag, Id},
value::{InputValue, Value},
visitor::Visitable,
};
use std::collections::{BTreeMap, BTreeSet};
pub use numeric_value::*;
pub use ic_memory::stable_structures::storable::Storable;
pub use serde::{Deserialize, Serialize, de::DeserializeOwned};
pub use std::{
cmp::{Eq, Ordering, PartialEq},
convert::From,
default::Default,
fmt::Debug,
hash::Hash,
ops::{Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Rem, Sub, SubAssign},
};
pub trait Path {
const PATH: &'static str;
}
pub trait Kind: Path + 'static {}
impl<T> Kind for T where T: Path + 'static {}
pub trait CanisterKind: Kind {
const COMMIT_MEMORY_ID: u8;
const COMMIT_STABLE_KEY: &'static str;
}
pub trait StoreKind: Kind {
type Canister: CanisterKind;
}
pub trait PersistedByKindCodec: Sized {
fn encode_persisted_slot_payload_by_kind(
&self,
kind: FieldKind,
field_name: &'static str,
) -> Result<Vec<u8>, InternalError>;
fn decode_persisted_option_slot_payload_by_kind(
bytes: &[u8],
kind: FieldKind,
field_name: &'static str,
) -> Result<Option<Self>, InternalError>;
}
pub trait PersistedStructuredFieldCodec {
fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError>;
fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError>
where
Self: Sized;
}
pub trait EntitySchema: EntityKey {
const NAME: &'static str;
const MODEL: &'static EntityModel;
}
pub trait EntityPlacement {
type Store: StoreKind<Canister = Self::Canister>;
type Canister: CanisterKind;
}
pub trait EntityKind: EntitySchema + 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 {}
pub trait TypeKind: Kind + Clone + DeserializeOwned + Visitable + PartialEq {}
impl<T> TypeKind for T where T: Kind + Clone + DeserializeOwned + PartialEq + Visitable {}
pub trait FieldTypeMeta {
const KIND: FieldKind;
const STORAGE_DECODE: FieldStorageDecode;
const NESTED_FIELDS: &'static [FieldModel] = &[];
}
impl<T> FieldTypeMeta for Option<T>
where
T: FieldTypeMeta,
{
const KIND: FieldKind = T::KIND;
const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
const NESTED_FIELDS: &'static [FieldModel] = T::NESTED_FIELDS;
}
impl<T> FieldTypeMeta for Box<T>
where
T: FieldTypeMeta,
{
const KIND: FieldKind = T::KIND;
const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
const NESTED_FIELDS: &'static [FieldModel] = T::NESTED_FIELDS;
}
impl<T> FieldTypeMeta for Vec<T>
where
T: FieldTypeMeta,
{
const KIND: FieldKind = FieldKind::List(&T::KIND);
const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
}
impl<T> FieldTypeMeta for BTreeSet<T>
where
T: FieldTypeMeta,
{
const KIND: FieldKind = FieldKind::Set(&T::KIND);
const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
}
impl<K, V> FieldTypeMeta for BTreeMap<K, V>
where
K: FieldTypeMeta,
V: FieldTypeMeta,
{
const KIND: FieldKind = FieldKind::Map {
key: &K::KIND,
value: &V::KIND,
};
const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
}
pub trait AuthoredFieldProjection {
fn get_input_value_by_index(&self, index: usize) -> Option<InputValue>;
}
pub trait FieldProjection {
fn get_value_by_index(&self, index: usize) -> Option<Value>;
}
pub trait Inner<T> {
fn inner(&self) -> &T;
fn into_inner(self) -> T;
}
pub trait Repr {
type Inner;
fn repr(&self) -> Self::Inner;
fn from_repr(inner: Self::Inner) -> Self;
}