Repository: GraphiteEditor/Graphite
File: node-graph/graph-craft/src/document.rs (Rust)

Code before:
	/// Due to the adaptive resolution system, nodes that take a `GraphicGroup` as input must call the upstream node with the `Footprint` parameter.
	///
	/// However, in the case of the default input, we must insert a node that takes an input of `Footprint` and returns `GraphicGroup::Empty`, in order to satisfy the type system.
	/// This is because the standard value node takes in `()`.
	pub fn resolve_empty_stacks(&mut self) {
		let new_id = generate_uuid();
		let mut used = false;

		for node in self.nodes.values_mut() {
			// Do not do this to the newly inserted empty stack (in case `resolve_empty_stacks` runs multiple times).
			if node.name == "Empty Stack" {
				continue;
			}
			for input in &mut node.inputs {
				if !matches!(
					input,
					NodeInput::Value {
						tagged_value: TaggedValue::GraphicGroup(GraphicGroup::EMPTY),
						..
					}
				) {
					continue;
				}

				*input = NodeInput::node(new_id, 0);
				used = true;
			}
		}

		// Only insert the node if necessary.
		if used {
			let new_node = DocumentNode {
				name: "Empty Stack".to_string(),
				implementation: DocumentNodeImplementation::proto("graphene_core::transform::CullNode<_>"),
				manual_composition: Some(concrete!(graphene_core::transform::Footprint)),
				inputs: vec![NodeInput::value(TaggedValue::GraphicGroup(graphene_core::GraphicGroup::EMPTY), false)],
				..Default::default()
			};
			self.nodes.insert(new_id, new_node);
		}
	}

	pub fn into_proto_networks(self) -> impl Iterator<Item = ProtoNetwork> {
		let mut nodes: Vec<_> = self.nodes.into_iter().map(|(id, node)| (id, node.resolve_proto_node())).collect();
		nodes.sort_unstable_by_key(|(i, _)| *i);

		// Create a network to evaluate each output
		self.outputs.into_iter().map(move |output| ProtoNetwork {
			inputs: self.inputs.clone(),
			output: output.node_id,
			nodes: nodes.clone(),

Review comment (suggestion):
Stylistic suggestion: invert this `if` statement by removing the preceding `!` and put the two lines inside the block in place of the `continue;` to save on a few lines.

Code after:
								if *output_node_id == id {
									*output_node_id = input_node_id;
									*output_output_index = output_index;
								}
							}
						}
						for NodeOutput {
							ref mut node_id,
							ref mut node_output_index,
						} in self.outputs.iter_mut()
						{
							if *node_id == id {
								*node_id = input_node_id;
								*node_output_index = output_index;
							}
						}
					}
				}
				self.nodes.remove(&id);
			}
		}
		Ok(())
	}

	/// Strips out any [`graphene_core::ops::IdNode`]s that are unnecessary.
	pub fn remove_redundant_id_nodes(&mut self) {
		let id_nodes = self
			.nodes
			.iter()
			.filter(|(_, node)| {
				matches!(&node.implementation, DocumentNodeImplementation::Unresolved(ident) if ident == &NodeIdentifier::new("graphene_core::ops::IdNode"))
					&& node.inputs.len() == 1
					&& matches!(node.inputs[0], NodeInput::Node { .. })
			})
			.map(|(id, _)| *id)
			.collect::<Vec<_>>();
		for id in id_nodes {
			if let Err(e) = self.remove_id_node(id) {
				log::warn!("{e}")
			}
		}
	}

	/// Converts the `DocumentNode`s with a `DocumentNodeImplementation::Extract` into a `ClonedNode` that returns
	/// the `DocumentNode` specified by the single `NodeInput::Node`.
	/// The referenced node is removed from the network, and any `NodeInput::Node`s used by the referenced node are replaced with a generically typed network input.
	pub fn resolve_extract_nodes(&mut self) {
		let mut extraction_nodes = self
			.nodes
			.iter()
			.filter(|(_, node)| matches!(node.implementation, DocumentNodeImplementation::Extract))