autosar_data/
iterators.rs

1use std::iter::FusedIterator;
2
3use super::*;
4
5#[doc(hidden)]
6pub struct ArxmlFileIterator {
7    data: AutosarModel,
8    index: usize,
9}
10
11impl ArxmlFileIterator {
12    pub(crate) fn new(data: AutosarModel) -> Self {
13        Self { data, index: 0 }
14    }
15}
16
17impl Iterator for ArxmlFileIterator {
18    type Item = ArxmlFile;
19
20    fn next(&mut self) -> Option<Self::Item> {
21        let model = self.data.0.read();
22        if self.index < model.files.len() {
23            let result = model.files[self.index].clone();
24            self.index += 1;
25            return Some(result);
26        }
27        None
28    }
29}
30
31#[doc(hidden)]
32pub struct ElementsIterator {
33    element: Element,
34    index: usize,
35    last_output: Option<Element>,
36}
37
38impl ElementsIterator {
39    pub(crate) fn new(element: Element) -> Self {
40        Self {
41            element,
42            index: 0,
43            last_output: None,
44        }
45    }
46}
47
48impl Iterator for ElementsIterator {
49    type Item = Element;
50
51    fn next(&mut self) -> Option<Self::Item> {
52        let element = self.element.0.read();
53        while self.index < element.content.len() {
54            let ec = &element.content[self.index];
55            if let ElementContent::Element(sub_element) = ec {
56                if let Some(prev_sub_element) = &self.last_output {
57                    if prev_sub_element != sub_element {
58                        // self.index does not point to the previously seen element
59                        // either self.index was already incremented in this loop, OR
60                        // an element was deleted from element.content since the last call to next()
61                        self.last_output = Some(sub_element.clone());
62                        return self.last_output.clone();
63                    } else {
64                        // self.index still points to the element that was returned by the previous call
65                        self.index += 1;
66                    }
67                } else {
68                    // return the first entry in element.content
69                    self.last_output = Some(sub_element.clone());
70                    return self.last_output.clone();
71                }
72            } else {
73                // skip character content
74                self.index += 1;
75            }
76        }
77        self.index = usize::MAX; // fused
78        None
79    }
80}
81
82impl FusedIterator for ElementsIterator {}
83
84#[doc(hidden)]
85pub struct ElementContentIterator {
86    element: Element,
87    index: usize,
88}
89
90impl Iterator for ElementContentIterator {
91    type Item = ElementContent;
92
93    fn next(&mut self) -> Option<Self::Item> {
94        let element = self.element.0.read();
95        if self.index < element.content.len() {
96            let ec = &element.content[self.index];
97            self.index += 1;
98            return Some(ec.clone());
99        }
100        None
101    }
102}
103
104impl ElementContentIterator {
105    pub(crate) fn new(element: &Element) -> Self {
106        Self {
107            element: element.clone(),
108            index: 0,
109        }
110    }
111}
112
113#[doc(hidden)]
114pub struct ArxmlFileElementsDfsIterator {
115    weak_file: WeakArxmlFile,
116    dfs_iter: Option<ElementsDfsIterator>,
117}
118
119impl ArxmlFileElementsDfsIterator {
120    pub(crate) fn new(file: &ArxmlFile, max_depth: usize) -> Self {
121        let weak_file = file.downgrade();
122        let dfs_iter = file.model().ok().map(|m| m.elements_dfs_with_max_depth(max_depth));
123        Self { weak_file, dfs_iter }
124    }
125}
126
127impl Iterator for ArxmlFileElementsDfsIterator {
128    type Item = (usize, Element);
129
130    fn next(&mut self) -> Option<Self::Item> {
131        let iter = self.dfs_iter.as_mut()?;
132        let mut next_element = iter.next();
133        while let Some((depth, elem)) = next_element {
134            let files = elem.file_membership_local();
135            if files.is_empty() || files.contains(&self.weak_file) {
136                // found an element that is present in this file
137                return Some((depth, elem));
138            }
139            // skip the current subtree
140            next_element = iter.next_sibling();
141        }
142        None
143    }
144}
145
146#[doc(hidden)]
147pub struct ElementsDfsIterator {
148    elements: Vec<Element>,
149    position: Vec<usize>,
150    max_depth: usize,
151}
152
153impl ElementsDfsIterator {
154    pub(crate) fn new(element: &Element, max_depth: usize) -> Self {
155        Self {
156            elements: vec![element.clone()],
157            position: vec![],
158            max_depth,
159        }
160    }
161
162    pub fn next_sibling(&mut self) -> Option<(usize, Element)> {
163        // when an element has bee returned, next always immediatly sets up to show its sub-elements
164        // to show a sibling instead we just need to discard the info related to the sub-element
165        self.elements.pop();
166        self.position.pop();
167        self.next()
168    }
169}
170
171impl Iterator for ElementsDfsIterator {
172    type Item = (usize, Element);
173
174    fn next(&mut self) -> Option<Self::Item> {
175        while !self.elements.is_empty() {
176            let depth = self.elements.len() - 1;
177            let element = &self.elements[depth];
178
179            if self.position.len() == depth {
180                // return the current element and set up to return its sub-elements next
181                self.position.push(0);
182
183                return Some((depth, element.clone()));
184            } else {
185                // return sub elements?
186                let max = self.max_depth;
187                if (max == 0 || max > depth) && element.content_item_count() > self.position[depth] {
188                    // more items to show
189                    if let Some(e) = element.get_sub_element_at(self.position[depth]) {
190                        self.elements.push(e);
191                    }
192                    // show the next item in the next call
193                    self.position[depth] += 1;
194                } else {
195                    // back up one level
196                    self.elements.pop();
197                    self.position.pop();
198                }
199            }
200        }
201
202        None
203    }
204}
205
206impl FusedIterator for ElementsDfsIterator {}
207
208#[doc(hidden)]
209pub struct AttributeIterator {
210    pub(crate) element: Element,
211    pub(crate) index: usize,
212}
213
214impl Iterator for AttributeIterator {
215    type Item = Attribute;
216
217    fn next(&mut self) -> Option<Self::Item> {
218        let element = self.element.0.read();
219        if self.index < element.attributes.len() {
220            let value = element.attributes[self.index].clone();
221            self.index += 1;
222            Some(value)
223        } else {
224            self.index = usize::MAX;
225            None
226        }
227    }
228}
229
230impl FusedIterator for AttributeIterator {}
231
232#[doc(hidden)]
233pub struct IdentifiablesIterator {
234    pub(crate) model: AutosarModel,
235    pub(crate) position: usize,
236}
237
238impl IdentifiablesIterator {
239    pub(crate) fn new(model: &AutosarModel) -> Self {
240        Self {
241            model: model.clone(),
242            position: 0,
243        }
244    }
245}
246
247impl Iterator for IdentifiablesIterator {
248    type Item = (String, WeakElement);
249
250    fn next(&mut self) -> Option<Self::Item> {
251        let model = self.model.0.read();
252        if self.position < model.identifiables.len() {
253            let pos = self.position;
254            self.position += 1;
255            model
256                .identifiables
257                .get_index(pos)
258                .map(|(key, elem)| (key.clone(), elem.clone()))
259        } else {
260            self.position = usize::MAX;
261            None
262        }
263    }
264}
265
266impl FusedIterator for IdentifiablesIterator {}
267
268#[cfg(test)]
269mod test {
270    use super::*;
271
272    #[test]
273    fn elements_iterator() {
274        let model = AutosarModel::new();
275        model.create_file("filename", AutosarVersion::LATEST).unwrap();
276        let element = model
277            .root_element()
278            .create_sub_element(ElementName::ArPackages)
279            .unwrap();
280        element
281            .create_named_sub_element(ElementName::ArPackage, "pkg1")
282            .unwrap();
283        element
284            .create_named_sub_element(ElementName::ArPackage, "pkg2")
285            .unwrap();
286        element
287            .create_named_sub_element(ElementName::ArPackage, "pkg3")
288            .unwrap();
289        element
290            .create_named_sub_element(ElementName::ArPackage, "pkg4")
291            .unwrap();
292
293        // verify that all elements are returned by the iterator
294        assert_eq!(element.sub_elements().count(), 4);
295        let mut iter = element.sub_elements();
296        assert_eq!(iter.next().unwrap().item_name().unwrap(), "pkg1");
297        assert_eq!(iter.next().unwrap().item_name().unwrap(), "pkg2");
298        assert_eq!(iter.next().unwrap().item_name().unwrap(), "pkg3");
299        assert_eq!(iter.next().unwrap().item_name().unwrap(), "pkg4");
300
301        // delete elements from the list while iterating
302        let mut steps = 0;
303        for se in element.sub_elements() {
304            element.remove_sub_element(se).unwrap();
305            steps += 1;
306        }
307        assert_eq!(steps, 4);
308        assert_eq!(element.sub_elements().count(), 0);
309    }
310
311    #[test]
312    fn elements_dfs_iterator() {
313        let sub_sub_element = ElementRaw {
314            parent: ElementOrModel::None,
315            elemname: ElementName::ArPackage, // doesn't matter for this test
316            elemtype: ElementType::ROOT,      // doesn't matter for this test
317            attributes: SmallVec::new(),
318            content: SmallVec::new(),
319            file_membership: HashSet::with_capacity(0),
320            comment: None,
321        }
322        .wrap();
323        let sub_element = ElementRaw {
324            parent: ElementOrModel::None,
325            elemname: ElementName::ArPackages, // doesn't matter for this test
326            elemtype: ElementType::ROOT,       // doesn't matter for this test
327            attributes: SmallVec::new(),
328            content: smallvec::smallvec![
329                ElementContent::Element(sub_sub_element.clone()),
330                ElementContent::Element(sub_sub_element.clone())
331            ],
332            file_membership: HashSet::with_capacity(0),
333            comment: None,
334        }
335        .wrap();
336        let element = ElementRaw {
337            parent: ElementOrModel::None,
338            elemname: ElementName::Autosar, // doesn't matter for this test
339            elemtype: ElementType::ROOT,    // doesn't matter for this test
340            attributes: SmallVec::new(),
341            content: smallvec::smallvec![
342                ElementContent::Element(sub_element.clone()),
343                ElementContent::Element(sub_element.clone())
344            ],
345            file_membership: HashSet::with_capacity(0),
346            comment: None,
347        }
348        .wrap();
349        let dfs_iter = element.elements_dfs();
350        assert_eq!(dfs_iter.count(), 7);
351    }
352
353    #[test]
354    fn elements_dfs_next_sibling() {
355        let model = AutosarModel::new();
356        model.create_file("test", AutosarVersion::LATEST).unwrap();
357        let el_autosar = model.root_element();
358        let el_ar_packages = el_autosar.create_sub_element(ElementName::ArPackages).unwrap();
359        let el_ar_package_1 = el_ar_packages
360            .create_named_sub_element(ElementName::ArPackage, "Package1")
361            .unwrap();
362        el_ar_package_1.create_sub_element(ElementName::Elements).unwrap();
363        let el_ar_package_2 = el_ar_packages
364            .create_named_sub_element(ElementName::ArPackage, "Package2")
365            .unwrap();
366        el_ar_package_2.create_sub_element(ElementName::Elements).unwrap();
367
368        let mut dfs_iter = model.elements_dfs();
369        let (_, item) = dfs_iter.next().unwrap();
370        assert_eq!(item, el_autosar);
371        let (_, item) = dfs_iter.next().unwrap();
372        assert_eq!(item, el_ar_packages);
373        let (_, item) = dfs_iter.next().unwrap();
374        assert_eq!(item, el_ar_package_1);
375        // next() would return the element ELEMENTS inside el_ar_package_1, but next_sibling should return el_ar_package_2 instead
376        let (_, item) = dfs_iter.next_sibling().unwrap();
377        assert_eq!(item, el_ar_package_2);
378    }
379
380    #[test]
381    fn identifiable_elements_iterator() {
382        let model = AutosarModel::new();
383        model.create_file("test", AutosarVersion::LATEST).unwrap();
384        let el_autosar = model.root_element();
385        let el_ar_packages = el_autosar.create_sub_element(ElementName::ArPackages).unwrap();
386        el_ar_packages
387            .create_named_sub_element(ElementName::ArPackage, "Package1")
388            .unwrap();
389        el_ar_packages
390            .create_named_sub_element(ElementName::ArPackage, "Package2")
391            .unwrap();
392
393        let iter = model.identifiable_elements();
394        assert_eq!(iter.count(), 2);
395    }
396}