rsconnect 0.2.2

Fine-grained reactivity in Rust
Documentation
use crate::{node_traits::DynComputedNode, utils::is_value_pointer_equal};

struct CyclicCheckVisitor {
	path_visitor: PathVisitor,
}

impl CyclicCheckVisitor {
	fn new() -> Self {
		Self {
			path_visitor: PathVisitor::new(),
		}
	}

	fn pre(&mut self, node: &'_ DynComputedNode) {
		if self.path_visitor.has_node(node) {
			panic!("Cyclic dependency");
		}
		self.path_visitor.pre(node);
	}

	fn post(&mut self) {
		self.path_visitor.post();
	}
}

struct PathVisitor {
	path: Vec<DynComputedNode>,
}

impl PathVisitor {
	fn new() -> Self {
		Self { path: Vec::new() }
	}

	fn has_node(&self, node: &'_ DynComputedNode) -> bool {
		self.path
			.iter()
			.any(|path_node| is_value_pointer_equal(path_node.as_ptr(), node.as_ptr()))
	}

	fn pre(&mut self, node: &'_ DynComputedNode) {
		self.path.push(node.clone());
	}

	fn post(&mut self) {
		self.path.pop();
	}
}

struct VisitedNodesVisitor {
	visited: Vec<DynComputedNode>,
}

impl VisitedNodesVisitor {
	fn new() -> Self {
		Self {
			visited: Vec::new(),
		}
	}

	fn should_enter(&self, node: &'_ DynComputedNode) -> bool {
		!self.visited.iter().any(|visited_node| {
			is_value_pointer_equal(visited_node.as_ptr(), node.as_ptr())
		})
	}

	fn post(&mut self, node: &'_ DynComputedNode) {
		self.visited.push(node.clone());
	}
}

pub(crate) struct ResolutionVisitor {
	cyclic_visitor: CyclicCheckVisitor,
	visited_nodes_visitor: VisitedNodesVisitor,
	resolved: Vec<DynComputedNode>,
}

impl ResolutionVisitor {
	pub(crate) fn new() -> Self {
		Self {
			cyclic_visitor: CyclicCheckVisitor::new(),
			visited_nodes_visitor: VisitedNodesVisitor::new(),
			resolved: Vec::new(),
		}
	}

	pub(crate) fn should_enter(&self, node: &'_ DynComputedNode) -> bool {
		self.visited_nodes_visitor.should_enter(node)
	}

	pub(crate) fn pre(&mut self, node: &'_ DynComputedNode) {
		self.cyclic_visitor.pre(node);
	}

	pub(crate) fn post(&mut self, node: &'_ DynComputedNode) {
		self.cyclic_visitor.post();
		self.visited_nodes_visitor.post(node);
		self.resolved.push(node.clone());
	}

	pub(crate) fn get_resolved(mut self) -> Vec<DynComputedNode> {
		self.resolved.reverse();
		self.resolved
	}
}