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 parents of a [`Model`].
70pub struct Parents {
71    model: Option<Model>,
72}
73
74impl Parents {
75    /// New parents iterator
76    pub fn new(model: Model) -> Self {
77        Self { model: Some(model) }
78    }
79}
80
81impl Iterator for Parents {
82    type Item = Model;
83
84    fn next(&mut self) -> Option<Self::Item> {
85        match &self.model {
86            Some(model) => {
87                let parent = model.borrow().parent.clone();
88                self.model = parent;
89                self.model.clone()
90            }
91            None => None,
92        }
93    }
94}
95
96/// Iterator over all ancestors (this model and its parents)
97pub struct Ancestors {
98    model: Option<Model>,
99}
100
101impl Ancestors {
102    /// New parents iterator
103    pub fn new(model: Model) -> Self {
104        Self { model: Some(model) }
105    }
106}
107
108impl Iterator for Ancestors {
109    type Item = Model;
110
111    fn next(&mut self) -> Option<Self::Item> {
112        let model = match &self.model {
113            Some(model) => model.clone(),
114            None => return None,
115        };
116
117        self.model = model.borrow().parent.clone();
118        Some(model.clone())
119    }
120}
121
122/// Iterator over all descendants.
123pub struct SourceFileDescendants {
124    stack: Models,
125    source_hash: u64,
126}
127
128impl SourceFileDescendants {
129    /// Create a new source file descendants.
130    pub fn new(root: Model) -> Self {
131        let source_hash = root.source_hash();
132
133        Self {
134            stack: root
135                .borrow()
136                .children
137                .filter_by_source_hash(source_hash)
138                .iter()
139                .rev()
140                .cloned()
141                .collect(),
142            source_hash,
143        }
144    }
145}
146
147impl Iterator for SourceFileDescendants {
148    type Item = Model;
149
150    fn next(&mut self) -> Option<Self::Item> {
151        if let Some(model) = self.stack.pop() {
152            let children = model
153                .borrow()
154                .children
155                .filter_by_source_hash(self.source_hash);
156            for child in children.iter().rev() {
157                self.stack.push(child.clone());
158            }
159
160            Some(model)
161        } else {
162            None
163        }
164    }
165}