Skip to content

Instantly share code, notes, and snippets.

@olson-sean-k
Last active October 2, 2020 23:16
Show Gist options
  • Save olson-sean-k/014e1b7e8edd15c093ff28dacfd75ce9 to your computer and use it in GitHub Desktop.
Save olson-sean-k/014e1b7e8edd15c093ff28dacfd75ce9 to your computer and use it in GitHub Desktop.
Journaled Storage with Dynamic Dispatch
#![feature(generic_associated_types)]
use std::collections::HashMap;
use std::ops::Deref;
use crate::borrow::Reborrow;
use crate::journal::{Journaled, Unjournaled};
pub type StorageObject<'a, E> = <<E as Entity>::Storage as Dispatch<E>>::Object<'a>;
mod hash {
use std::collections::HashMap;
use std::hash::Hash;
use crate::journal::Unjournaled;
use crate::{
AsStorage, Dispatch, Entity, ExtrinsicStorage, Get, InsertWithKey, Remove, StorageObject,
};
impl<E, K> AsStorage<E> for HashMap<K, E>
where
E: Entity<Key = K, Storage = HashMap<K, E>>,
K: Eq + Hash,
{
fn as_storage(&self) -> &StorageObject<E> {
self
}
}
impl<E, K> Dispatch<E> for HashMap<K, E>
where
E: Entity<Key = K, Storage = HashMap<K, E>>,
K: Eq + Hash,
{
type Object<'a> where E: 'a = dyn 'a + ExtrinsicStorage<E>;
}
impl<E> Get<E> for HashMap<E::Key, E>
where
E: Entity,
E::Key: Eq + Hash,
{
fn get(&self, key: E::Key) -> Option<&E> {
HashMap::get(self, &key)
}
fn get_mut(&mut self, key: E::Key) -> Option<&mut E> {
HashMap::get_mut(self, &key)
}
}
impl<E> InsertWithKey<E> for HashMap<E::Key, E>
where
E: Entity,
E::Key: Eq + Hash,
{
fn insert_with_key(&mut self, entity: E, key: E::Key) -> Option<E> {
HashMap::insert(self, key, entity)
}
}
impl<E> Remove<E> for HashMap<E::Key, E>
where
E: Entity,
E::Key: Eq + Hash,
{
fn remove(&mut self, key: E::Key) -> Option<E> {
HashMap::remove(self, &key)
}
}
impl<K, T> Unjournaled for HashMap<K, T> where K: Eq + Hash {}
}
mod journal {
use crate::{AsStorage, Entity, Get, Insert, InsertWithKey, Remove, StorageObject};
// TODO: Require this marker trait to construct a `MeshGraph` via
// `Entity::Storage`. The mutation API can require `Journaled` and
// `Core` can remain flexible (constrained as needed).
pub trait Unjournaled {}
#[derive(Default)]
pub struct Journaled<T>
where
T: 'static,
{
storage: T,
// ...,
}
impl<T> Journaled<T> {
pub fn new(storage: T) -> Self {
Journaled { storage }
}
}
impl<T, E> AsStorage<E> for Journaled<T>
where
T: AsStorage<E>,
E: Entity,
{
fn as_storage(&self) -> &StorageObject<E> {
self.storage.as_storage()
}
}
impl<T, E> Get<E> for Journaled<T>
where
T: Get<E>,
E: Entity,
{
fn get(&self, key: E::Key) -> Option<&E> {
todo!()
}
fn get_mut(&mut self, key: E::Key) -> Option<&mut E> {
todo!()
}
}
impl<T, E> Insert<E> for Journaled<T>
where
T: Insert<E>,
E: Entity,
{
fn insert(&mut self, entity: E) -> Option<E::Key> {
todo!()
}
}
impl<T, E> InsertWithKey<E> for Journaled<T>
where
T: InsertWithKey<E>,
E: Entity,
{
fn insert_with_key(&mut self, entity: E, key: E::Key) -> Option<E> {
todo!()
}
}
impl<T, E> Remove<E> for Journaled<T>
where
T: Remove<E>,
E: Entity,
{
fn remove(&mut self, key: E::Key) -> Option<E> {
todo!()
}
}
}
pub mod borrow {
pub trait Reborrow {
type Target;
fn reborrow(&self) -> &Self::Target;
}
pub trait ReborrowMut: Reborrow {
fn reborrow_mut(&mut self) -> &mut Self::Target;
}
pub trait ReborrowInto<'a>: Reborrow {
fn reborrow_into(self) -> &'a Self::Target;
}
impl<'a, T> Reborrow for &'a T {
type Target = T;
fn reborrow(&self) -> &Self::Target {
*self
}
}
impl<'a, T> Reborrow for &'a mut T {
type Target = T;
fn reborrow(&self) -> &Self::Target {
&**self
}
}
impl<'a, T> ReborrowMut for &'a mut T {
fn reborrow_mut(&mut self) -> &mut Self::Target {
*self
}
}
impl<'a, T> ReborrowInto<'a> for &'a T {
fn reborrow_into(self) -> &'a Self::Target {
self
}
}
impl<'a, T> ReborrowInto<'a> for &'a mut T {
fn reborrow_into(self) -> &'a Self::Target {
&*self
}
}
}
pub trait Entity: Sized {
type Key: Copy + Eq;
type Storage: Default + Dispatch<Self> + Storage<Self> + Unjournaled;
}
impl Entity for () {
type Key = ();
type Storage = HashMap<Self::Key, Self>;
}
pub trait Dispatch<E>
where
E: Entity,
{
type Object<'a>: 'a + ?Sized + Storage<E>
where
E: 'a;
}
pub trait Get<E>
where
E: Entity,
{
fn get(&self, key: E::Key) -> Option<&E>;
fn get_mut(&mut self, key: E::Key) -> Option<&mut E>;
}
pub trait Insert<E>
where
E: Entity,
{
fn insert(&mut self, entity: E) -> Option<E::Key>;
}
pub trait InsertWithKey<E>
where
E: Entity,
{
fn insert_with_key(&mut self, entity: E, key: E::Key) -> Option<E>;
}
pub trait Remove<E>
where
E: Entity,
{
fn remove(&mut self, key: E::Key) -> Option<E>;
}
pub trait Storage<E>: AsStorage<E> + Get<E> + Remove<E>
where
E: Entity,
{
}
impl<T, E> Storage<E> for T
where
T: AsStorage<E> + Get<E> + Remove<E>,
E: Entity,
{
}
pub trait ExtrinsicStorage<E>: InsertWithKey<E> + Storage<E>
where
E: Entity,
{
}
impl<T, E> ExtrinsicStorage<E> for T
where
T: InsertWithKey<E> + Storage<E>,
E: Entity,
{
}
pub trait IntrinsicStorage<E>: Insert<E> + Storage<E>
where
E: Entity,
{
}
impl<T, E> IntrinsicStorage<E> for T
where
T: Insert<E> + Storage<E>,
E: Entity,
{
}
pub trait AsStorage<E>
where
E: Entity,
{
fn as_storage(&self) -> &StorageObject<E>;
}
impl<'a, E, T> AsStorage<E> for &'a T
where
E: Entity,
T: AsStorage<E>,
{
fn as_storage(&self) -> &StorageObject<E> {
<T as AsStorage<E>>::as_storage(self)
}
}
impl<'a, E, T> AsStorage<E> for &'a mut T
where
E: Entity,
T: AsStorage<E>,
{
fn as_storage(&self) -> &StorageObject<E> {
<T as AsStorage<E>>::as_storage(self)
}
}
pub trait AsStorageMut<E>: AsStorage<E>
where
E: Entity,
{
fn as_storage_mut(&mut self) -> &mut StorageObject<E>;
}
impl<'a, E, T> AsStorageMut<E> for &'a mut T
where
E: Entity,
T: AsStorageMut<E>,
{
fn as_storage_mut(&mut self) -> &mut StorageObject<E> {
<T as AsStorageMut<E>>::as_storage_mut(self)
}
}
pub struct View<B, E>
where
B: Reborrow,
B::Target: AsStorage<E>,
E: Entity,
{
storage: B,
key: E::Key,
}
impl<B, E> Deref for View<B, E>
where
B: Reborrow,
B::Target: AsStorage<E>,
E: Entity,
{
type Target = E;
fn deref(&self) -> &Self::Target {
self.storage.reborrow().as_storage().get(self.key).expect("")
}
}
fn read(storage: impl AsStorage<()>, key: <() as Entity>::Key) {
let storage = storage.as_storage();
if let Some(entity) = storage.get(key) {}
}
fn main() {
let storage = <() as Entity>::Storage::default();
read(&storage, ());
let storage = <() as Entity>::Storage::default();
let storage = Journaled::new(storage);
read(&storage, ());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment