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        while let Some(ref model) = self.stack.pop() {
95            let model_ = model.borrow();
96            if matches!(model_.element(), Element::Multiplicity) {
97                // Expand but don't yield this node itself
98                self.stack.extend(model_.children.iter().rev().cloned());
99                continue;
100            }
101            // Return only non-multiplicity elements
102            return Some(model.clone());
103        }
104        None
105    }
106}
107
108/// Iterator over all parents of a [`Model`].
109pub struct Parents {
110    model: Option<Model>,
111}
112
113impl Parents {
114    /// New parents iterator
115    pub fn new(model: Model) -> Self {
116        Self { model: Some(model) }
117    }
118}
119
120impl Iterator for Parents {
121    type Item = Model;
122
123    fn next(&mut self) -> Option<Self::Item> {
124        match &self.model {
125            Some(model) => {
126                let parent = model.borrow().parent.clone();
127                self.model = parent;
128                self.model.clone()
129            }
130            None => None,
131        }
132    }
133}
134
135/// Iterator over all ancestors (this model and its parents)
136pub struct Ancestors {
137    model: Option<Model>,
138}
139
140impl Ancestors {
141    /// New parents iterator
142    pub fn new(model: Model) -> Self {
143        Self { model: Some(model) }
144    }
145}
146
147impl Iterator for Ancestors {
148    type Item = Model;
149
150    fn next(&mut self) -> Option<Self::Item> {
151        let model = match &self.model {
152            Some(model) => model.clone(),
153            None => return None,
154        };
155
156        self.model = model.borrow().parent.clone();
157        Some(model.clone())
158    }
159}
160
161/// Iterator over all descendants.
162pub struct SourceFileDescendants {
163    stack: Models,
164    source_hash: u64,
165}
166
167impl SourceFileDescendants {
168    /// Create a new source file descendants.
169    pub fn new(root: Model) -> Self {
170        let source_hash = root.source_hash();
171
172        Self {
173            stack: root
174                .borrow()
175                .children
176                .filter_by_source_hash(source_hash)
177                .iter()
178                .rev()
179                .cloned()
180                .collect(),
181            source_hash,
182        }
183    }
184}
185
186impl Iterator for SourceFileDescendants {
187    type Item = Model;
188
189    fn next(&mut self) -> Option<Self::Item> {
190        if let Some(model) = self.stack.pop() {
191            let children = model
192                .borrow()
193                .children
194                .filter_by_source_hash(self.source_hash);
195            for child in children.iter().rev() {
196                self.stack.push(child.clone());
197            }
198
199            Some(model)
200        } else {
201            None
202        }
203    }
204}