1pub mod filter;
7pub mod mode;
8pub mod profile;
9
10pub use filter::filter_node;
11pub use mode::LoadMode;
12pub use profile::LoadError;
13
14use crate::model::file::AgmFile;
15
16#[must_use]
24pub fn load(file: &AgmFile, mode: LoadMode) -> AgmFile {
25 let nodes = file.nodes.iter().map(|n| filter_node(n, mode)).collect();
26
27 AgmFile {
28 header: file.header.clone(),
29 nodes,
30 }
31}
32
33#[must_use]
42pub fn load_nodes(file: &AgmFile, mode: LoadMode, node_ids: &[&str]) -> AgmFile {
43 let id_set: std::collections::HashSet<&str> = node_ids.iter().copied().collect();
44
45 let nodes = file
46 .nodes
47 .iter()
48 .filter(|n| id_set.contains(n.id.as_str()))
49 .map(|n| filter_node(n, mode))
50 .collect();
51
52 AgmFile {
53 header: file.header.clone(),
54 nodes,
55 }
56}
57
58pub fn load_profile(file: &AgmFile, profile_name: Option<&str>) -> Result<AgmFile, LoadError> {
66 profile::resolve_and_apply(file, profile_name)
67}
68
69#[cfg(test)]
74mod tests {
75 use crate::model::fields::{NodeType, Priority, Span};
76 use crate::model::file::{AgmFile, Header};
77 use crate::model::node::Node;
78
79 use super::*;
80
81 fn minimal_header() -> Header {
82 Header {
83 agm: "1.0".to_owned(),
84 package: "test.pkg".to_owned(),
85 version: "0.1.0".to_owned(),
86 title: None,
87 owner: None,
88 imports: None,
89 default_load: None,
90 description: None,
91 tags: None,
92 status: None,
93 load_profiles: None,
94 target_runtime: None,
95 }
96 }
97
98 fn make_node(id: &str) -> Node {
99 Node {
100 id: id.to_owned(),
101 node_type: NodeType::Facts,
102 summary: format!("node {id}"),
103 priority: Some(Priority::High),
104 items: Some(vec!["item1".to_owned()]),
105 detail: Some("full detail".to_owned()),
106 span: Span::new(1, 5),
107 ..Default::default()
108 }
109 }
110
111 fn make_file(nodes: Vec<Node>) -> AgmFile {
112 AgmFile {
113 header: minimal_header(),
114 nodes,
115 }
116 }
117
118 #[test]
119 fn test_load_returns_all_nodes_filtered() {
120 let file = make_file(vec![make_node("a"), make_node("b")]);
121 let result = load(&file, LoadMode::Summary);
122 assert_eq!(result.nodes.len(), 2);
123 assert!(result.nodes[0].detail.is_none());
125 assert!(result.nodes[1].detail.is_none());
126 assert!(result.nodes[0].priority.is_some());
128 }
129
130 #[test]
131 fn test_load_nodes_returns_only_requested_ids() {
132 let file = make_file(vec![make_node("a"), make_node("b"), make_node("c")]);
133 let result = load_nodes(&file, LoadMode::Summary, &["a", "c"]);
134 assert_eq!(result.nodes.len(), 2);
135 let ids: Vec<&str> = result.nodes.iter().map(|n| n.id.as_str()).collect();
136 assert!(ids.contains(&"a"));
137 assert!(ids.contains(&"c"));
138 assert!(!ids.contains(&"b"));
139 }
140
141 #[test]
142 fn test_load_nodes_preserves_file_order() {
143 let file = make_file(vec![make_node("x"), make_node("y"), make_node("z")]);
144 let result = load_nodes(&file, LoadMode::Summary, &["z", "x"]);
145 assert_eq!(result.nodes[0].id, "x");
147 assert_eq!(result.nodes[1].id, "z");
148 }
149
150 #[test]
151 fn test_load_nodes_ignores_unknown_ids() {
152 let file = make_file(vec![make_node("a")]);
153 let result = load_nodes(&file, LoadMode::Summary, &["a", "nonexistent"]);
154 assert_eq!(result.nodes.len(), 1);
155 assert_eq!(result.nodes[0].id, "a");
156 }
157}