hcl/structure/
iter.rs

1//! Iterators over HCL structures.
2
3use super::{Attribute, Block, Body, Structure};
4use std::iter::FusedIterator;
5use std::slice;
6use std::vec;
7
8macro_rules! impl_find_map_iterator {
9    ($ty:ident$(<$lt:lifetime>)?, $item:ty, $map:expr) => {
10        impl$(<$lt>)* Iterator for $ty$(<$lt>)* {
11            type Item = $item;
12
13            fn next(&mut self) -> Option<Self::Item> {
14                self.iter.find_map($map)
15            }
16        }
17
18        impl$(<$lt>)* DoubleEndedIterator for $ty$(<$lt>)* {
19            fn next_back(&mut self) -> Option<Self::Item> {
20                loop {
21                    match self.iter.next_back() {
22                        Some(val) => {
23                            if let Some(val) = $map(val) {
24                                return Some(val);
25                            }
26                        }
27                        None => return None,
28                    };
29                }
30            }
31        }
32
33        impl$(<$lt>)* FusedIterator for $ty$(<$lt>)* {}
34    };
35}
36
37macro_rules! impl_exact_size_iterator {
38    ($ty:ident$(<$lt:lifetime>)?, $item:ty) => {
39        impl$(<$lt>)* Iterator for $ty$(<$lt>)* {
40            type Item = $item;
41
42            fn next(&mut self) -> Option<Self::Item> {
43                self.iter.next()
44            }
45
46            fn size_hint(&self) -> (usize, Option<usize>) {
47                self.iter.size_hint()
48            }
49        }
50
51        impl$(<$lt>)* DoubleEndedIterator for $ty$(<$lt>)* {
52            fn next_back(&mut self) -> Option<Self::Item> {
53                self.iter.next_back()
54            }
55        }
56
57        impl$(<$lt>)* ExactSizeIterator for $ty$(<$lt>)* {
58            fn len(&self) -> usize {
59                self.iter.len()
60            }
61        }
62
63        impl$(<$lt>)* FusedIterator for $ty$(<$lt>)* {}
64    };
65}
66
67impl<T> Extend<T> for Body
68where
69    T: Into<Structure>,
70{
71    fn extend<I>(&mut self, iterable: I)
72    where
73        I: IntoIterator<Item = T>,
74    {
75        self.0.extend(iterable.into_iter().map(Into::into));
76    }
77}
78
79impl<T> FromIterator<T> for Body
80where
81    T: Into<Structure>,
82{
83    fn from_iter<I>(iter: I) -> Self
84    where
85        I: IntoIterator<Item = T>,
86    {
87        let iter = iter.into_iter();
88        let lower = iter.size_hint().0;
89        let mut body = Body(Vec::with_capacity(lower));
90        body.extend(iter);
91        body
92    }
93}
94
95impl IntoIterator for Body {
96    type Item = Structure;
97
98    type IntoIter = IntoIter;
99
100    fn into_iter(self) -> Self::IntoIter {
101        IntoIter::new(self)
102    }
103}
104
105impl<'a> IntoIterator for &'a Body {
106    type Item = &'a Structure;
107
108    type IntoIter = Iter<'a>;
109
110    fn into_iter(self) -> Self::IntoIter {
111        self.iter()
112    }
113}
114
115impl<'a> IntoIterator for &'a mut Body {
116    type Item = &'a mut Structure;
117
118    type IntoIter = IterMut<'a>;
119
120    fn into_iter(self) -> Self::IntoIter {
121        self.iter_mut()
122    }
123}
124
125/// An iterator over the structures within a `Body`.
126///
127/// This `struct` is created by the [`iter`][Body::iter] method on [`Body`]. See its documentation
128/// for more.
129#[derive(Debug, Clone)]
130pub struct Iter<'a> {
131    iter: slice::Iter<'a, Structure>,
132}
133
134impl<'a> Iter<'a> {
135    pub(super) fn new(body: &'a Body) -> Iter<'a> {
136        Iter {
137            iter: body.0.iter(),
138        }
139    }
140}
141
142impl_exact_size_iterator!(Iter<'a>, &'a Structure);
143
144/// A mutable iterator over the structures within a `Body`.
145///
146/// This `struct` is created by the [`iter_mut`][Body::iter_mut] method on [`Body`]. See its
147/// documentation for more.
148#[derive(Debug)]
149pub struct IterMut<'a> {
150    iter: slice::IterMut<'a, Structure>,
151}
152
153impl<'a> IterMut<'a> {
154    pub(super) fn new(body: &'a mut Body) -> IterMut<'a> {
155        IterMut {
156            iter: body.0.iter_mut(),
157        }
158    }
159}
160
161impl_exact_size_iterator!(IterMut<'a>, &'a mut Structure);
162
163/// An owning iterator over the structures within a `Body`.
164///
165/// This `struct` is created by the [`into_iter`] method on [`Body`] (provided by the
166/// [`IntoIterator`] trait). See its documentation for more.
167///
168/// [`into_iter`]: IntoIterator::into_iter
169/// [`IntoIterator`]: core::iter::IntoIterator
170#[derive(Debug, Clone)]
171pub struct IntoIter {
172    iter: vec::IntoIter<Structure>,
173}
174
175impl IntoIter {
176    pub(super) fn new(body: Body) -> IntoIter {
177        IntoIter {
178            iter: body.0.into_iter(),
179        }
180    }
181}
182
183impl_exact_size_iterator!(IntoIter, Structure);
184
185/// An iterator over the attributes within a `Body`.
186///
187/// This `struct` is created by the [`attributes`][Body::attributes] method on [`Body`]. See its
188/// documentation for more.
189#[derive(Debug, Clone)]
190pub struct Attributes<'a> {
191    iter: Iter<'a>,
192}
193
194impl<'a> Attributes<'a> {
195    pub(super) fn new(body: &'a Body) -> Attributes<'a> {
196        Attributes { iter: body.iter() }
197    }
198}
199
200impl_find_map_iterator!(Attributes<'a>, &'a Attribute, Structure::as_attribute);
201
202/// A mutable iterator over the attributes within a `Body`.
203///
204/// This `struct` is created by the [`attributes_mut`][Body::attributes_mut] method on [`Body`].
205/// See its documentation for more.
206#[derive(Debug)]
207pub struct AttributesMut<'a> {
208    iter: IterMut<'a>,
209}
210
211impl<'a> AttributesMut<'a> {
212    pub(super) fn new(body: &'a mut Body) -> AttributesMut<'a> {
213        AttributesMut {
214            iter: body.iter_mut(),
215        }
216    }
217}
218
219impl_find_map_iterator!(
220    AttributesMut<'a>,
221    &'a mut Attribute,
222    Structure::as_attribute_mut
223);
224
225/// An owning iterator over the attributes within a `Body`.
226///
227/// This `struct` is created by the [`into_attributes`][Body::into_attributes] method on [`Body`].
228/// See its documentation for more.
229#[derive(Debug, Clone)]
230pub struct IntoAttributes {
231    iter: IntoIter,
232}
233
234impl IntoAttributes {
235    pub(super) fn new(body: Body) -> IntoAttributes {
236        IntoAttributes {
237            iter: body.into_iter(),
238        }
239    }
240}
241
242impl_find_map_iterator!(IntoAttributes, Attribute, Structure::into_attribute);
243
244/// An iterator over the blocks within a `Body`.
245///
246/// This `struct` is created by the [`blocks`][Body::blocks] method on [`Body`]. See its
247/// documentation for more.
248#[derive(Debug, Clone)]
249pub struct Blocks<'a> {
250    iter: Iter<'a>,
251}
252
253impl<'a> Blocks<'a> {
254    pub(super) fn new(body: &'a Body) -> Blocks<'a> {
255        Blocks { iter: body.iter() }
256    }
257}
258
259impl_find_map_iterator!(Blocks<'a>, &'a Block, Structure::as_block);
260
261/// A mutable iterator over the blocks within a `Body`.
262///
263/// This `struct` is created by the [`blocks_mut`][Body::blocks_mut] method on [`Body`]. See its
264/// documentation for more.
265#[derive(Debug)]
266pub struct BlocksMut<'a> {
267    iter: IterMut<'a>,
268}
269
270impl<'a> BlocksMut<'a> {
271    pub(super) fn new(body: &'a mut Body) -> BlocksMut<'a> {
272        BlocksMut {
273            iter: body.iter_mut(),
274        }
275    }
276}
277
278impl_find_map_iterator!(BlocksMut<'a>, &'a mut Block, Structure::as_block_mut);
279
280/// An owning iterator over the blocks within a `Body`.
281///
282/// This `struct` is created by the [`into_blocks`][Body::into_blocks] method on [`Body`]. See its
283/// documentation for more.
284#[derive(Debug, Clone)]
285pub struct IntoBlocks {
286    iter: IntoIter,
287}
288
289impl IntoBlocks {
290    pub(super) fn new(body: Body) -> IntoBlocks {
291        IntoBlocks {
292            iter: body.into_iter(),
293        }
294    }
295}
296
297impl_find_map_iterator!(IntoBlocks, Block, Structure::into_block);