use std::debug_assert_eq;
use std::cell::RefCell;
use std::cmp::Eq;
use std::collections::HashMap;
use std::error;
use std::hash::Hash;
use std::marker::PhantomData;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::rc::Rc;
use display_derive::Display;
use typemap::TypeMap;
pub struct Persistent<'store, Key, Value>
where
Key: Copy + Eq + Hash + 'static,
Value: 'static,
{
store: &'store Store,
key: Key,
value: Option<Value>,
}
impl<'store, Key, Value> Persistent<'store, Key, Value>
where
Key: Copy + Eq + Hash + 'static,
Value: 'static,
{
pub fn get_key(&self) -> Key {
self.key
}
}
impl<'store, Key, Value> Drop for Persistent<'store, Key, Value>
where
Key: Copy + Eq + Hash + 'static,
Value: 'static,
{
fn drop(&mut self) {
let value = mem::replace(&mut self.value, None).expect("Internal Error: value should not be None");
self.store.r#return(self.key, value);
}
}
impl<'store, Key, Value> Deref for Persistent<'store, Key, Value>
where
Key: Copy + Eq + Hash + 'static,
Value: 'static,
{
type Target = Value;
fn deref(&self) -> &Self::Target {
self.value.as_ref().expect("Internal Error: value should not be None.")
}
}
impl<'store, Key, Value> DerefMut for Persistent<'store, Key, Value>
where
Key: Copy + Eq + Hash + 'static,
Value: 'static,
{
fn deref_mut(&mut self) -> &mut Self::Target {
self.value.as_mut().expect("Internal Error: value should not be None.")
}
}
#[derive(Clone)]
pub struct PersistentRef<Key, Value>
where
Key: Copy + Eq + Hash + 'static,
Value: 'static,
{
key: Key,
value: Rc<Value>,
}
impl<Key, Value> PersistentRef<Key, Value>
where
Key: Copy + Eq + Hash + 'static,
Value: 'static,
{
pub fn get_key(&self) -> Key {
self.key
}
}
impl<Key, Value> Deref for PersistentRef<Key, Value>
where
Key: Copy + Eq + Hash + 'static,
Value: 'static,
{
type Target = Value;
fn deref(&self) -> &Self::Target {
&*self.value
}
}
struct TypeKey<Key, Value>(PhantomData<(Key, Value)>);
impl<Key, Value> typemap::Key for TypeKey<Key, Value>
where
Key: 'static,
Value: 'static,
{
type Value = HashMap<Key, State<Value>>;
}
enum State<Item> {
InStore(Rc<Item>),
Locked,
}
#[derive(Debug, Display)]
pub enum StoreError {
#[display(fmt = "the specified (key, type) pair already exists in the store")]
Existing,
}
impl error::Error for StoreError {}
#[derive(Debug, Display)]
pub enum LockError {
#[display(fmt = "the specified (key, type) pair doesn't exist in the store")]
NotFound,
#[display(fmt = "the queried item is already locked")]
Locked,
#[display(fmt = "the queried item is currently borrowed")]
Borrowed,
}
impl error::Error for LockError {}
#[derive(Debug, Display)]
pub enum BorrowError {
#[display(fmt = "the specified type, key pair doesn't exist in the store")]
NotFound,
#[display(fmt = "the queried item is already locked")]
Locked,
}
impl error::Error for BorrowError {}
pub struct Store {
map: RefCell<TypeMap>,
}
impl Store {
pub fn new() -> Self {
Self {
map: RefCell::new(TypeMap::new()),
}
}
pub fn store<Key, Value>(&self, key: Key, value: Value) -> Result<(), StoreError>
where
Key: Copy + Eq + Hash + 'static,
Value: 'static,
{
let mut map = self.map.borrow_mut();
if !map.contains::<TypeKey<Key, Value>>() {
map.insert::<TypeKey<Key, Value>>(HashMap::new());
}
let hash_map = map.get_mut::<TypeKey<Key, Value>>().unwrap();
if hash_map.contains_key(&key) {
Err(StoreError::Existing)?;
}
if hash_map.insert(key, State::InStore(Rc::new(value))).is_some() {
panic!("Internal Error: item should not exist in store")
};
Ok(())
}
pub fn lock<Key, Value>(&self, key: Key) -> Result<Persistent<Key, Value>, LockError>
where
Key: Copy + Eq + Hash + 'static,
Value: 'static,
{
let mut map = self.map.borrow_mut();
let hash_map = match map.get_mut::<TypeKey<Key, Value>>() {
Some(hash_map) => hash_map,
None => return Err(LockError::NotFound),
};
let value = match hash_map.get_mut(&key) {
Some(value) => value,
None => return Err(LockError::NotFound),
};
match value {
State::InStore(value) => {
if Rc::strong_count(value) != 1 {
return Err(LockError::Borrowed);
}
},
State::Locked => return Err(LockError::Locked),
}
let value = match mem::replace(value, State::Locked) {
State::InStore(value) => value,
_ => panic!("Internal Error: value should exist in store"),
};
Ok(Persistent{store: self, key, value: Some(Rc::try_unwrap(value).ok().expect("Internal Error: value shouldn't be borrowed"))})
}
pub fn borrow<Key, Value>(&self, key: Key) -> Result<PersistentRef<Key, Value>, BorrowError>
where
Key: Copy + Eq + Hash + 'static,
Value: 'static,
{
let mut map = self.map.borrow_mut();
let hash_map = match map.get_mut::<TypeKey<Key, Value>>() {
Some(hash_map) => hash_map,
None => return Err(BorrowError::NotFound),
};
let value = match hash_map.get_mut(&key) {
Some(value) => value,
None => return Err(BorrowError::NotFound),
};
let value = match value {
State::InStore(value) => value.clone(),
_ => return Err(BorrowError::Locked),
};
Ok(PersistentRef{key, value})
}
fn r#return<Key, Value>(&self, key: Key, value: Value)
where
Key: Copy + Eq + Hash + 'static,
Value: 'static,
{
let mut map = self.map.borrow_mut();
let hash_map = map.get_mut::<TypeKey<Key, Value>>().expect("Internal Error: key should exist in store.");
let retrived_mark = hash_map.get_mut(&key).expect("Internal Error: key should exist in store.");
debug_assert_eq!(mem::discriminant(retrived_mark), mem::discriminant(&State::Locked));
mem::replace(retrived_mark, State::InStore(Rc::new(value)));
}
}
impl Default for Store {
fn default() -> Self {
Self::new()
}
}