use crate::computable::{Computable, InnerValue};
use crate::{AsmErr, AsmResult, ComputableAccessor, ComputableOwner, ComputableSizedVec, ComputableSizedVecAccessor, ComputableSizedVecOwner};
use std::cell::UnsafeCell;
use std::sync::Arc;
impl<V> Default for InnerValue<V> {
fn default() -> Self { InnerValue::UnInit }
}
impl<V> Default for Computable<V> {
fn default() -> Self {
Self { inner_value: Default::default() }
}
}
impl<V: Clone> Clone for Computable<V> {
fn clone(&self) -> Self {
let inner_value = unsafe { &mut *self.inner_value.get() };
let cloned_inner = inner_value.clone();
Self { inner_value: UnsafeCell::new(cloned_inner) }
}
}
impl<T, V> ComputableAccessor<V> for T
where
T: ComputableOwner<V>,
{
fn force(&self) -> AsmResult<Arc<V>> {
self.computable_ref().force_with_fn(|| self.compute())
}
}
impl<V> Computable<V> {
pub fn force_with_fn(&self, f: impl FnOnce() -> AsmResult<V>) -> AsmResult<Arc<V>> {
let inner_value_ptr = self.inner_value.get();
let inner = unsafe { &mut *inner_value_ptr };
match inner {
InnerValue::UnInit => {
let value = Arc::new(f()?);
let copied = value.clone();
*inner = InnerValue::Initialized(value);
Ok(copied)
}
InnerValue::Initialized(value) => Ok(Arc::clone(value))
}
}
}
impl<V> ComputableSizedVec<V> {
pub fn new(size: usize) -> Self {
let mut vec = Vec::with_capacity(size);
vec.resize_with(size, || Default::default());
Self { vec_ref: vec }
}
}
impl<T, V> ComputableSizedVecAccessor<V> for T
where
T: ComputableSizedVecOwner<V>,
{
fn get_or_compute(&self, index: usize) -> AsmResult<Arc<V>> {
self.computable_vec().vec_ref.get(index)
.ok_or_else(|| AsmErr::OutOfRange(index))?
.force_with_fn(|| self.compute(index))
}
}