use std::iter::FusedIterator;
use super::*;
#[doc(hidden)]
pub struct ArxmlFileIterator {
data: AutosarModel,
index: usize,
}
impl ArxmlFileIterator {
pub(crate) fn new(data: AutosarModel) -> Self {
Self { data, index: 0 }
}
}
impl Iterator for ArxmlFileIterator {
type Item = ArxmlFile;
fn next(&mut self) -> Option<Self::Item> {
let model = self.data.0.read();
if self.index < model.files.len() {
let result = model.files[self.index].clone();
self.index += 1;
return Some(result);
}
None
}
}
#[doc(hidden)]
pub struct ElementsIterator {
element: Element,
index: usize,
last_output: Option<Element>,
}
impl ElementsIterator {
pub(crate) fn new(element: Element) -> Self {
Self {
element,
index: 0,
last_output: None,
}
}
}
impl Iterator for ElementsIterator {
type Item = Element;
fn next(&mut self) -> Option<Self::Item> {
let element = self.element.0.read();
while self.index < element.content.len() {
let ec = &element.content[self.index];
if let ElementContent::Element(sub_element) = ec {
if let Some(prev_sub_element) = &self.last_output {
if prev_sub_element != sub_element {
self.last_output = Some(sub_element.clone());
return self.last_output.clone();
} else {
self.index += 1;
}
} else {
self.last_output = Some(sub_element.clone());
return self.last_output.clone();
}
} else {
self.index += 1;
}
}
self.index = usize::MAX; None
}
}
impl FusedIterator for ElementsIterator {}
#[doc(hidden)]
pub struct ElementContentIterator {
element: Element,
index: usize,
}
impl Iterator for ElementContentIterator {
type Item = ElementContent;
fn next(&mut self) -> Option<Self::Item> {
let element = self.element.0.read();
if self.index < element.content.len() {
let ec = &element.content[self.index];
self.index += 1;
return Some(ec.clone());
}
None
}
}
impl ElementContentIterator {
pub(crate) fn new(element: &Element) -> Self {
Self {
element: element.clone(),
index: 0,
}
}
}
#[doc(hidden)]
pub struct ArxmlFileElementsDfsIterator {
weak_file: WeakArxmlFile,
dfs_iter: Option<ElementsDfsIterator>,
}
impl ArxmlFileElementsDfsIterator {
pub(crate) fn new(file: &ArxmlFile, max_depth: usize) -> Self {
let weak_file = file.downgrade();
let dfs_iter = file.model().ok().map(|m| m.elements_dfs_with_max_depth(max_depth));
Self { weak_file, dfs_iter }
}
}
impl Iterator for ArxmlFileElementsDfsIterator {
type Item = (usize, Element);
fn next(&mut self) -> Option<Self::Item> {
let iter = self.dfs_iter.as_mut()?;
let mut next_element = iter.next();
while let Some((depth, elem)) = next_element {
let files = elem.file_membership_local();
if files.is_empty() || files.contains(&self.weak_file) {
return Some((depth, elem));
}
next_element = iter.next_sibling();
}
None
}
}
#[doc(hidden)]
pub struct ElementsDfsIterator {
elements: Vec<Element>,
position: Vec<usize>,
max_depth: usize,
}
impl ElementsDfsIterator {
pub(crate) fn new(element: &Element, max_depth: usize) -> Self {
Self {
elements: vec![element.clone()],
position: vec![],
max_depth,
}
}
pub fn next_sibling(&mut self) -> Option<(usize, Element)> {
self.elements.pop();
self.position.pop();
self.next()
}
}
impl Iterator for ElementsDfsIterator {
type Item = (usize, Element);
fn next(&mut self) -> Option<Self::Item> {
while !self.elements.is_empty() {
let depth = self.elements.len() - 1;
let element = &self.elements[depth];
if self.position.len() == depth {
self.position.push(0);
return Some((depth, element.clone()));
} else {
let max = self.max_depth;
if (max == 0 || max > depth) && element.content_item_count() > self.position[depth] {
if let Some(e) = element.get_sub_element_at(self.position[depth]) {
self.elements.push(e);
}
self.position[depth] += 1;
} else {
self.elements.pop();
self.position.pop();
}
}
}
None
}
}
impl FusedIterator for ElementsDfsIterator {}
#[doc(hidden)]
pub struct AttributeIterator {
pub(crate) element: Element,
pub(crate) index: usize,
}
impl Iterator for AttributeIterator {
type Item = Attribute;
fn next(&mut self) -> Option<Self::Item> {
let element = self.element.0.read();
if self.index < element.attributes.len() {
let value = element.attributes[self.index].clone();
self.index += 1;
Some(value)
} else {
self.index = usize::MAX;
None
}
}
}
impl FusedIterator for AttributeIterator {}
#[doc(hidden)]
pub struct IdentifiablesIterator {
pub(crate) model: AutosarModel,
pub(crate) position: usize,
}
impl IdentifiablesIterator {
pub(crate) fn new(model: &AutosarModel) -> Self {
Self {
model: model.clone(),
position: 0,
}
}
}
impl Iterator for IdentifiablesIterator {
type Item = (String, WeakElement);
fn next(&mut self) -> Option<Self::Item> {
let model = self.model.0.read();
if self.position < model.identifiables.len() {
let pos = self.position;
self.position += 1;
model
.identifiables
.get_index(pos)
.map(|(key, elem)| (key.clone(), elem.clone()))
} else {
self.position = usize::MAX;
None
}
}
}
impl FusedIterator for IdentifiablesIterator {}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn elements_iterator() {
let model = AutosarModel::new();
model.create_file("filename", AutosarVersion::LATEST).unwrap();
let element = model
.root_element()
.create_sub_element(ElementName::ArPackages)
.unwrap();
element
.create_named_sub_element(ElementName::ArPackage, "pkg1")
.unwrap();
element
.create_named_sub_element(ElementName::ArPackage, "pkg2")
.unwrap();
element
.create_named_sub_element(ElementName::ArPackage, "pkg3")
.unwrap();
element
.create_named_sub_element(ElementName::ArPackage, "pkg4")
.unwrap();
assert_eq!(element.sub_elements().count(), 4);
let mut iter = element.sub_elements();
assert_eq!(iter.next().unwrap().item_name().unwrap(), "pkg1");
assert_eq!(iter.next().unwrap().item_name().unwrap(), "pkg2");
assert_eq!(iter.next().unwrap().item_name().unwrap(), "pkg3");
assert_eq!(iter.next().unwrap().item_name().unwrap(), "pkg4");
let mut steps = 0;
for se in element.sub_elements() {
element.remove_sub_element(se).unwrap();
steps += 1;
}
assert_eq!(steps, 4);
assert_eq!(element.sub_elements().count(), 0);
}
#[test]
fn elements_dfs_iterator() {
let sub_sub_element = ElementRaw {
parent: ElementOrModel::None,
elemname: ElementName::ArPackage, elemtype: ElementType::ROOT, attributes: SmallVec::new(),
content: SmallVec::new(),
file_membership: HashSet::with_capacity(0),
comment: None,
}
.wrap();
let sub_element = ElementRaw {
parent: ElementOrModel::None,
elemname: ElementName::ArPackages, elemtype: ElementType::ROOT, attributes: SmallVec::new(),
content: smallvec::smallvec![
ElementContent::Element(sub_sub_element.clone()),
ElementContent::Element(sub_sub_element.clone())
],
file_membership: HashSet::with_capacity(0),
comment: None,
}
.wrap();
let element = ElementRaw {
parent: ElementOrModel::None,
elemname: ElementName::Autosar, elemtype: ElementType::ROOT, attributes: SmallVec::new(),
content: smallvec::smallvec![
ElementContent::Element(sub_element.clone()),
ElementContent::Element(sub_element.clone())
],
file_membership: HashSet::with_capacity(0),
comment: None,
}
.wrap();
let dfs_iter = element.elements_dfs();
assert_eq!(dfs_iter.count(), 7);
}
#[test]
fn elements_dfs_next_sibling() {
let model = AutosarModel::new();
model.create_file("test", AutosarVersion::LATEST).unwrap();
let el_autosar = model.root_element();
let el_ar_packages = el_autosar.create_sub_element(ElementName::ArPackages).unwrap();
let el_ar_package_1 = el_ar_packages
.create_named_sub_element(ElementName::ArPackage, "Package1")
.unwrap();
el_ar_package_1.create_sub_element(ElementName::Elements).unwrap();
let el_ar_package_2 = el_ar_packages
.create_named_sub_element(ElementName::ArPackage, "Package2")
.unwrap();
el_ar_package_2.create_sub_element(ElementName::Elements).unwrap();
let mut dfs_iter = model.elements_dfs();
let (_, item) = dfs_iter.next().unwrap();
assert_eq!(item, el_autosar);
let (_, item) = dfs_iter.next().unwrap();
assert_eq!(item, el_ar_packages);
let (_, item) = dfs_iter.next().unwrap();
assert_eq!(item, el_ar_package_1);
let (_, item) = dfs_iter.next_sibling().unwrap();
assert_eq!(item, el_ar_package_2);
}
#[test]
fn identifiable_elements_iterator() {
let model = AutosarModel::new();
model.create_file("test", AutosarVersion::LATEST).unwrap();
let el_autosar = model.root_element();
let el_ar_packages = el_autosar.create_sub_element(ElementName::ArPackages).unwrap();
el_ar_packages
.create_named_sub_element(ElementName::ArPackage, "Package1")
.unwrap();
el_ar_packages
.create_named_sub_element(ElementName::ArPackage, "Package2")
.unwrap();
let iter = model.identifiable_elements();
assert_eq!(iter.count(), 2);
}
}