-
-
Save olson-sean-k/014e1b7e8edd15c093ff28dacfd75ce9 to your computer and use it in GitHub Desktop.
Journaled Storage with Dynamic Dispatch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![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