rsconnect 0.2.2

Fine-grained reactivity in Rust
Documentation
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);
		}
	}
}