use std::{
cell::{Ref, RefCell},
marker::PhantomData,
rc::Rc,
};
use crate::{
comparable_value::{ComparableValue, NonComparableValue, Value},
connect_structs::Connect,
node_traits::{
ComputedNode, ConnectNode, DynComputedNode, DynNode, Node, NodeValueAccess,
WeakDynComputedNode,
},
};
pub type ConnectObserved<T> = Rc<RefCell<Observed<T, ComparableValue<T>>>>;
pub type ConnectObservedAny<T> = Rc<RefCell<Observed<T, NonComparableValue<T>>>>;
pub type ConnectComputed<T, F> = Rc<RefCell<Computed<T, ComparableValue<T>, F>>>;
pub type ConnectComputedAny<T, F> = Rc<RefCell<Computed<T, NonComparableValue<T>, F>>>;
pub type ConnectEffected<T, F, E> = Rc<RefCell<Effected<T, ComparableValue<T>, F, E>>>;
pub type ConnectEffectedAny<T, F, E> =
Rc<RefCell<Effected<T, NonComparableValue<T>, F, E>>>;
pub struct Observed<T, V: Value<T>> {
value: V,
derived: Vec<WeakDynComputedNode>,
value_type: PhantomData<T>,
}
impl<T: PartialEq> Observed<T, ComparableValue<T>> {
pub(crate) fn new(value: T) -> Self {
Self {
value: ComparableValue(value),
derived: Vec::new(),
value_type: PhantomData,
}
}
}
impl<T> Observed<T, NonComparableValue<T>> {
pub(crate) fn new(value: T) -> Self {
Self {
value: NonComparableValue(value),
derived: Vec::new(),
value_type: PhantomData,
}
}
}
pub struct Computed<T, V: Value<T>, F: Fn(&mut Connect) -> T> {
comp_fun: F,
value: V,
derived: Vec<WeakDynComputedNode>,
dependencies: Vec<ConnectNode>,
}
impl<T, V: Value<T>, F: Fn(&mut Connect) -> T> Drop for Computed<T, V, F> {
fn drop(&mut self) {
for dependency in self.get_dependencies() {
match dependency {
ConnectNode::Observed(dependency)
| ConnectNode::ObservedAny(dependency) => dependency
.borrow_mut()
.get_mut_derived()
.retain(|derived| derived.strong_count() > 0),
ConnectNode::Computed(dependency)
| ConnectNode::ComputedAny(dependency)
| ConnectNode::Effected(dependency)
| ConnectNode::EffectedAny(dependency) => dependency
.borrow_mut()
.get_mut_derived()
.retain(|derived| derived.strong_count() > 0),
}
}
}
}
impl<T: PartialEq, F: Fn(&mut Connect) -> T> Computed<T, ComparableValue<T>, F> {
pub(crate) fn new(comp_fun: F, value: T, dependencies: Vec<ConnectNode>) -> Self {
Self {
value: ComparableValue(value),
comp_fun,
derived: Vec::new(),
dependencies,
}
}
}
impl<T, F: Fn(&mut Connect) -> T> Computed<T, NonComparableValue<T>, F> {
pub(crate) fn new(comp_fun: F, value: T, dependencies: Vec<ConnectNode>) -> Self {
Self {
value: NonComparableValue(value),
comp_fun,
derived: Vec::new(),
dependencies,
}
}
}
pub struct Effected<T, V: Value<T>, F: Fn(&mut Connect) -> T, E: FnMut(&T)> {
comp_fun: F,
value: V,
effect: E,
derived: Vec<WeakDynComputedNode>,
dependencies: Vec<ConnectNode>,
}
impl<T, V: Value<T>, F: Fn(&mut Connect) -> T, E: FnMut(&T)> Drop
for Effected<T, V, F, E>
{
fn drop(&mut self) {
for dependency in self.get_dependencies() {
match dependency {
ConnectNode::Observed(dependency)
| ConnectNode::ObservedAny(dependency) => dependency
.borrow_mut()
.get_mut_derived()
.retain(|derived| derived.strong_count() > 0),
ConnectNode::Computed(dependency)
| ConnectNode::ComputedAny(dependency)
| ConnectNode::Effected(dependency)
| ConnectNode::EffectedAny(dependency) => dependency
.borrow_mut()
.get_mut_derived()
.retain(|derived| derived.strong_count() > 0),
}
}
}
}
impl<T: PartialEq, F: Fn(&mut Connect) -> T, E: FnMut(&T)>
Effected<T, ComparableValue<T>, F, E>
{
pub(crate) fn new(
comp_fun: F,
value: T,
effect: E,
dependencies: Vec<ConnectNode>,
) -> Self {
Self {
value: ComparableValue(value),
comp_fun,
effect,
derived: Vec::new(),
dependencies,
}
}
}
impl<T, F: Fn(&mut Connect) -> T, E: FnMut(&T)> Effected<T, NonComparableValue<T>, F, E> {
pub(crate) fn new(
comp_fun: F,
value: T,
effect: E,
dependencies: Vec<ConnectNode>,
) -> Self {
Self {
value: NonComparableValue(value),
comp_fun,
effect,
derived: Vec::new(),
dependencies,
}
}
}
impl<T, V: Value<T>> Node for Observed<T, V> {
fn get_derived(&self) -> &Vec<WeakDynComputedNode> {
&self.derived
}
fn get_mut_derived(&mut self) -> &mut Vec<WeakDynComputedNode> {
&mut self.derived
}
}
impl<T, V: Value<T>, F: Fn(&mut Connect) -> T> Node for Computed<T, V, F> {
fn get_derived(&self) -> &Vec<WeakDynComputedNode> {
&self.derived
}
fn get_mut_derived(&mut self) -> &mut Vec<WeakDynComputedNode> {
&mut self.derived
}
}
impl<T, V: Value<T>, F: Fn(&mut Connect) -> T> ComputedNode for Computed<T, V, F> {
fn get_dependencies(&self) -> &Vec<ConnectNode> {
&self.dependencies
}
fn recalculate(&mut self, c: &mut Connect) -> bool {
let value = self.value.set_own((self.comp_fun)(c));
!self.value.equal(&value)
}
fn set_dependencies(&mut self, dependencies: Vec<ConnectNode>) {
self.dependencies = dependencies;
}
fn run_effect(&mut self) {}
}
impl<T, V: Value<T>, F: Fn(&mut Connect) -> T, E: FnMut(&T)> Node
for Effected<T, V, F, E>
{
fn get_derived(&self) -> &Vec<WeakDynComputedNode> {
&self.derived
}
fn get_mut_derived(&mut self) -> &mut Vec<WeakDynComputedNode> {
&mut self.derived
}
}
impl<T, V: Value<T>, F: Fn(&mut Connect) -> T, E: FnMut(&T)> ComputedNode
for Effected<T, V, F, E>
{
fn get_dependencies(&self) -> &Vec<ConnectNode> {
&self.dependencies
}
fn recalculate(&mut self, c: &mut Connect) -> bool {
let value = self.value.set_own((self.comp_fun)(c));
!self.value.equal(&value)
}
fn set_dependencies(&mut self, dependencies: Vec<ConnectNode>) {
self.dependencies = dependencies;
}
fn run_effect(&mut self) {
(self.effect)(self.value.get_ref())
}
}
impl<T, V: Value<T>> NodeValueAccess for Rc<RefCell<Observed<T, V>>> {
type Value = T;
type CompFun = ();
fn get_inert(&self) -> Ref<T> {
Ref::map(self.borrow(), |observed| observed.value.get_ref())
}
fn set_inert(&self, value: T) -> T {
self.borrow_mut().value.set_own(value)
}
fn equal(&self, value: &T) -> bool {
self.borrow().value.equal(value)
}
}
impl<T, V: Value<T>, F: Fn(&mut Connect) -> T> NodeValueAccess
for Rc<RefCell<Computed<T, V, F>>>
{
type Value = T;
type CompFun = F;
fn get_inert(&self) -> Ref<T> {
Ref::map(self.borrow(), |observed| observed.value.get_ref())
}
fn set_inert(&self, value: T) -> T {
self.borrow_mut().value.set_own(value)
}
fn equal(&self, _value: &T) -> bool {
false
}
}
impl<T: PartialEq + 'static> From<ConnectObserved<T>> for ConnectNode {
fn from(node: ConnectObserved<T>) -> ConnectNode {
ConnectNode::Observed(node as DynNode)
}
}
impl<T: 'static> From<ConnectObservedAny<T>> for ConnectNode {
fn from(node: ConnectObservedAny<T>) -> ConnectNode {
ConnectNode::ObservedAny(node as DynNode)
}
}
impl<T: PartialEq + 'static, F: Fn(&mut Connect) -> T + 'static>
From<ConnectComputed<T, F>> for ConnectNode
{
fn from(node: ConnectComputed<T, F>) -> ConnectNode {
ConnectNode::Computed(node as DynComputedNode)
}
}
impl<T: 'static, F: Fn(&mut Connect) -> T + 'static> From<ConnectComputedAny<T, F>>
for ConnectNode
{
fn from(node: ConnectComputedAny<T, F>) -> ConnectNode {
ConnectNode::ComputedAny(node as DynComputedNode)
}
}