microcad_lang/model/
iter.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Model tree iterators
5
6use super::*;
7
8/// Children iterator struct.
9pub struct Children {
10    model: Model,
11    index: usize,
12}
13
14impl Children {
15    /// Create new [`Children`] iterator
16    pub fn new(model: Model) -> Self {
17        Self { model, index: 0 }
18    }
19}
20
21impl Iterator for Children {
22    type Item = Model;
23
24    fn next(&mut self) -> Option<Self::Item> {
25        let model = self.model.borrow();
26        let child = model.children.get(self.index);
27        self.index += 1;
28        child.cloned()
29    }
30}
31
32/// Iterator over all descendants.
33pub struct Descendants {
34    stack: Models,
35}
36
37impl Descendants {
38    /// Create new descendants iterator
39    pub fn new(root: Model) -> Self {
40        Self {
41            stack: root
42                .borrow()
43                .children
44                .iter()
45                .rev()
46                .cloned()
47                .collect::<Vec<_>>()
48                .into(),
49        }
50    }
51}
52
53impl Iterator for Descendants {
54    type Item = Model;
55
56    fn next(&mut self) -> Option<Self::Item> {
57        if let Some(model) = self.stack.pop() {
58            let children = model.borrow().children.clone();
59            for child in children.iter().rev() {
60                self.stack.push(child.clone());
61            }
62            Some(model)
63        } else {
64            None
65        }
66    }
67}
68
69/// Iterator over all descendants of multiplicities.
70pub struct MultiplicityDescendants {
71    stack: Models,
72}
73
74impl MultiplicityDescendants {
75    /// Create new descendants iterator
76    pub fn new(root: Model) -> Self {
77        Self {
78            stack: root
79                .borrow()
80                .children
81                .iter()
82                .rev()
83                .cloned()
84                .collect::<Vec<_>>()
85                .into(),
86        }
87    }
88}
89
90impl Iterator for MultiplicityDescendants {
91    type Item = Model;
92
93    fn next(&mut self) -> Option<Self::Item> {
94        let model = self.stack.pop();
95        if let Some(ref model) = model {
96            let model_ = model.borrow();
97            if matches!(model_.element(), Element::Multiplicity) {
98                self.stack.extend(model_.children.iter().rev().cloned());
99            }
100        }
101        model
102    }
103}
104
105/// Iterator over all parents of a [`Model`].
106pub struct Parents {
107    model: Option<Model>,
108}
109
110impl Parents {
111    /// New parents iterator
112    pub fn new(model: Model) -> Self {
113        Self { model: Some(model) }
114    }
115}
116
117impl Iterator for Parents {
118    type Item = Model;
119
120    fn next(&mut self) -> Option<Self::Item> {
121        match &self.model {
122            Some(model) => {
123                let parent = model.borrow().parent.clone();
124                self.model = parent;
125                self.model.clone()
126            }
127            None => None,
128        }
129    }
130}
131
132/// Iterator over all ancestors (this model and its parents)
133pub struct Ancestors {
134    model: Option<Model>,
135}
136
137impl Ancestors {
138    /// New parents iterator
139    pub fn new(model: Model) -> Self {
140        Self { model: Some(model) }
141    }
142}
143
144impl Iterator for Ancestors {
145    type Item = Model;
146
147    fn next(&mut self) -> Option<Self::Item> {
148        let model = match &self.model {
149            Some(model) => model.clone(),
150            None => return None,
151        };
152
153        self.model = model.borrow().parent.clone();
154        Some(model.clone())
155    }
156}
157
158/// Iterator over all descendants.
159pub struct SourceFileDescendants {
160    stack: Models,
161    source_hash: u64,
162}
163
164impl SourceFileDescendants {
165    /// Create a new source file descendants.
166    pub fn new(root: Model) -> Self {
167        let source_hash = root.source_hash();
168
169        Self {
170            stack: root
171                .borrow()
172                .children
173                .filter_by_source_hash(source_hash)
174                .iter()
175                .rev()
176                .cloned()
177                .collect(),
178            source_hash,
179        }
180    }
181}
182
183impl Iterator for SourceFileDescendants {
184    type Item = Model;
185
186    fn next(&mut self) -> Option<Self::Item> {
187        if let Some(model) = self.stack.pop() {
188            let children = model
189                .borrow()
190                .children
191                .filter_by_source_hash(self.source_hash);
192            for child in children.iter().rev() {
193                self.stack.push(child.clone());
194            }
195
196            Some(model)
197        } else {
198            None
199        }
200    }
201}