use std::any::{Any, TypeId};
use std::collections::HashMap;
mod errors;
mod hasher;
mod many;
mod map;
mod refcell_unit;
mod storageunit;
mod unit;
pub use errors::{DynamicResult, ErrorDesc, UnitError};
use hasher::PassthroughHasherBuilder;
pub use many::{Fetch, FetchMultiple};
pub use map::{Map, MapMut};
pub use refcell_unit::{DynamicStorage, RefCellUnit};
pub use storageunit::StorageUnit;
pub use unit::{Unit, Waitable};
#[derive(Default)]
pub struct BlackBox<U: ?Sized> {
pub(crate) data: HashMap<TypeId, Box<U>, PassthroughHasherBuilder>,
}
pub(crate) type Borrowed<'a, T> = <T as Unit<'a>>::Borrowed;
pub(crate) type MutBorrowed<'a, T> = <T as Unit<'a>>::MutBorrowed;
impl<U: ?Sized + for<'a> Unit<'a>> BlackBox<U> {
pub fn new() -> Self {
Self {
data: HashMap::with_hasher(PassthroughHasherBuilder),
}
}
#[inline]
pub fn has_unit<T: 'static>(&self) -> bool {
self.data.contains_key(&TypeId::of::<T>())
}
pub fn insert<T: 'static>(&self, data: T) -> Result<(), (T, ErrorDesc)> {
let entry = self.data.get(&TypeId::of::<T>());
match entry {
Some(x) => match x.insert_any(Box::new(data)) {
Some((x, e)) => Err((*x.downcast().unwrap(), e)),
None => Ok(()),
},
None => Err((data, ErrorDesc::NoAllocatedUnit)),
}
}
pub fn waiting_insert<'a, T: 'static>(&'a self, data: T) -> Result<(), (T, ErrorDesc)>
where
Borrowed<'a, U>: Waitable,
MutBorrowed<'a, U>: Waitable,
{
let entry = self.data.get(&TypeId::of::<T>());
match entry {
Some(x) => match x.waiting_insert(Box::new(data)) {
Some((x, e)) => Err((*x.downcast().unwrap(), e)),
None => Ok(()),
},
None => Err((data, ErrorDesc::NoAllocatedUnit)),
}
}
pub fn insert_many<T: 'static>(&self, data: Vec<T>) -> Result<(), (Vec<T>, ErrorDesc)> {
let entry = self.data.get(&TypeId::of::<T>());
match entry {
Some(x) => match x.insert_any(Box::new(data)) {
Some((x, e)) => Err((*x.downcast().unwrap(), e)),
None => Ok(()),
},
None => Err((data, ErrorDesc::NoAllocatedUnit)),
}
}
pub fn waiting_insert_many<'a, T: 'static>(
&'a self,
data: Vec<T>,
) -> Result<(), (Vec<T>, ErrorDesc)>
where
Borrowed<'a, U>: Waitable,
MutBorrowed<'a, U>: Waitable,
{
let entry = self.data.get(&TypeId::of::<T>());
match entry {
Some(x) => match x.waiting_insert(Box::new(data)) {
Some((x, e)) => Err((*x.downcast().unwrap(), e)),
None => Ok(()),
},
None => Err((data, ErrorDesc::NoAllocatedUnit)),
}
}
#[inline]
pub(crate) fn unit_get<T: 'static>(&self) -> DynamicResult<&U> {
self.data
.get(&TypeId::of::<T>())
.map(|x| &**x)
.ok_or(ErrorDesc::NoAllocatedUnit)
}
pub fn run_for<'a, 'b, T: 'static, D: 'static + Any, F: FnMut(&[T]) -> D + 'a>(
&'b self,
mut f: F,
) -> DynamicResult<D>
where
Borrowed<'b, U>: Map<dyn Any, StorageUnit<T>, Func = dyn Fn(&dyn Any) -> &StorageUnit<T>>,
{
let unit = self.unit_get::<T>()?;
let dynstorage = unit.storage()?;
let conv_func: &dyn for<'r> Fn(&'r dyn Any) -> &'r StorageUnit<T> =
&|x| x.downcast_ref::<StorageUnit<T>>().unwrap();
let storage = Map::map(dynstorage, conv_func);
Ok(f(storage.many()?))
}
pub fn waiting_run_for<'a, 'b, T: 'static, D: 'static + Any, F: FnMut(&[T]) -> D + 'a>(
&'b self,
mut f: F,
) -> DynamicResult<D>
where
Borrowed<'b, U>:
Map<dyn Any, StorageUnit<T>, Func = dyn Fn(&dyn Any) -> &StorageUnit<T>> + Waitable,
{
let unit = self.unit_get::<T>()?;
let dynstorage = unit.waiting_storage();
let conv_func: &dyn for<'r> Fn(&'r dyn Any) -> &'r StorageUnit<T> =
&|x| x.downcast_ref::<StorageUnit<T>>().unwrap();
let storage = Map::map(dynstorage, conv_func);
Ok(f(storage.many()?))
}
pub fn run_for_mut<'a, 'b, T: 'static, D: 'static + Any, F: FnMut(&mut Vec<T>) -> D + 'a>(
&'b self,
mut f: F,
) -> DynamicResult<D>
where
MutBorrowed<'b, U>:
MapMut<dyn Any, StorageUnit<T>, Func = dyn Fn(&mut dyn Any) -> &mut StorageUnit<T>>,
{
let unit = self.unit_get::<T>()?;
let dynstorage = unit.storage_mut()?;
let conv_func: &dyn for<'r> Fn(&'r mut dyn Any) -> &'r mut StorageUnit<T> =
&|x: &mut dyn Any| x.downcast_mut::<StorageUnit<T>>().unwrap();
let mut storage = MapMut::map(dynstorage, conv_func);
let res = f(storage.many_mut()?);
storage.rearrange_if_necessary();
Ok(res)
}
pub fn waiting_run_for_mut<
'a,
'b,
T: 'static,
D: 'static + Any,
F: FnMut(&mut Vec<T>) -> D + 'a,
>(
&'b self,
mut f: F,
) -> DynamicResult<D>
where
MutBorrowed<'b, U>:
MapMut<dyn Any, StorageUnit<T>, Func = dyn Fn(&mut dyn Any) -> &mut StorageUnit<T>>
+ Waitable,
{
let unit = self.unit_get::<T>()?;
let dynstorage = unit.waiting_storage_mut();
let conv_func: &dyn for<'r> Fn(&'r mut dyn Any) -> &'r mut StorageUnit<T> =
&|x: &mut dyn Any| x.downcast_mut::<StorageUnit<T>>().unwrap();
let mut storage = MapMut::map(dynstorage, conv_func);
let res = f(storage.many_mut()?);
storage.rearrange_if_necessary();
Ok(res)
}
#[inline(always)]
pub fn get<'a, T: FetchMultiple<'a, U>>(&'a self) -> DynamicResult<T::Output> {
T::get_many(self)
}
#[inline(always)]
pub fn waiting_get<'a, T: FetchMultiple<'a, U>>(&'a self) -> DynamicResult<T::Output>
where
Borrowed<'a, U>: Waitable,
MutBorrowed<'a, U>: Waitable,
{
T::waiting_get_many(self)
}
}