use std::collections::HashMap; use cfgsync_artifacts::{ArtifactFile, ArtifactSet}; use serde::{Deserialize, Serialize}; /// Fully materialized cfgsync artifacts for a registration set. /// /// `nodes` holds the node-local files keyed by stable node identifier. /// `shared` holds files that should be delivered alongside every node. #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct MaterializedArtifacts { nodes: HashMap, shared: ArtifactSet, } impl MaterializedArtifacts { /// Creates materialized artifacts from node-local artifact sets. #[must_use] pub fn from_nodes(nodes: I) -> Self where I: IntoIterator, { Self { nodes: nodes.into_iter().collect(), shared: ArtifactSet::default(), } } /// Attaches shared files delivered alongside every node. #[must_use] pub fn with_shared(mut self, shared: ArtifactSet) -> Self { self.shared = shared; self } /// Returns the node-local artifact set for one identifier. #[must_use] pub fn node(&self, identifier: &str) -> Option<&ArtifactSet> { self.nodes.get(identifier) } /// Returns the shared artifact set. #[must_use] pub fn shared(&self) -> &ArtifactSet { &self.shared } /// Returns the number of node-local artifact sets. #[must_use] pub fn len(&self) -> usize { self.nodes.len() } /// Returns `true` when no node-local artifact sets are present. #[must_use] pub fn is_empty(&self) -> bool { self.nodes.is_empty() } /// Resolves the full file set that should be written for one node. #[must_use] pub fn resolve(&self, identifier: &str) -> Option { let node = self.node(identifier)?; let mut files: Vec = node.files.clone(); files.extend(self.shared.files.iter().cloned()); Some(ArtifactSet::new(files)) } /// Iterates node-local artifact sets by stable identifier. pub fn iter(&self) -> impl Iterator { self.nodes .iter() .map(|(identifier, artifacts)| (identifier.as_str(), artifacts)) } }