use std::rc::Rc;
use crate::{
connect_structs::{Connect, Recalculation},
node_traits::{ConnectNode, DynComputedNode, RefNode},
utils::is_value_pointer_equal,
};
pub(crate) trait NodeUpdate {
fn start_shared_update(&mut self);
fn stop_shared_update(&mut self) -> Vec<ConnectNode>;
fn get_computed_value<T, F: FnOnce(&mut Connect) -> T>(
&mut self,
comp_fun: F,
) -> (T, Vec<ConnectNode>);
fn add_to_current_update_dependencies(&mut self, node: &ConnectNode);
fn add_to_derived(&self, computed: &DynComputedNode, dependency: &ConnectNode);
fn remove_from_derived(&self, computed: &DynComputedNode, dependency: &ConnectNode);
}
impl NodeUpdate for Connect {
fn start_shared_update(&mut self) {
self.recalculation = Some(Recalculation::new());
}
fn stop_shared_update(&mut self) -> Vec<ConnectNode> {
if let Some(recalculation) = std::mem::replace(&mut self.recalculation, None) {
recalculation.dependencies
} else {
Vec::new()
}
}
fn get_computed_value<T, F: FnOnce(&mut Connect) -> T>(
&mut self,
comp_fun: F,
) -> (T, Vec<ConnectNode>) {
self.start_shared_update();
let value = comp_fun(self);
(value, self.stop_shared_update())
}
fn add_to_current_update_dependencies(&mut self, node: &ConnectNode) {
if let Some(recalculation) = &mut self.recalculation {
if !recalculation.dependencies.iter().any(|dependency| {
is_value_pointer_equal(dependency.as_value_ptr(), node.as_value_ptr())
}) {
recalculation.dependencies.push(node.clone());
}
}
}
fn add_to_derived(&self, computed: &DynComputedNode, dependency: &ConnectNode) {
let mut derived = dependency.get_mut_derived();
if !derived
.iter()
.filter_map(|derived_node| derived_node.upgrade())
.any(|derived_node| {
is_value_pointer_equal(derived_node.as_ptr(), computed.as_ptr())
}) {
derived.push(Rc::downgrade(computed));
}
}
fn remove_from_derived(&self, computed: &DynComputedNode, dependency: &ConnectNode) {
let mut derived = dependency.get_mut_derived();
if let Some(index) = derived
.iter()
.filter_map(|derived_node| derived_node.upgrade())
.position(|derived_node| {
is_value_pointer_equal(derived_node.as_ptr(), computed.as_ptr())
}) {
derived.remove(index);
}
}
}