Skip to content

Commit b7a721f

Browse files
committed
Added iterator over mutable children
1 parent 69e02d6 commit b7a721f

File tree

2 files changed

+108
-1
lines changed

2 files changed

+108
-1
lines changed

src/iter.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::iter::FusedIterator;
22
use std::ops::Range;
33
use std::{slice, vec};
44

5-
use crate::{Node, NodeId, NodeRef, Tree};
5+
use crate::{Node, NodeId, NodeMut, NodeRef, Tree};
66

77
/// Iterator that moves out of a tree in insert order.
88
#[derive(Debug)]
@@ -216,6 +216,52 @@ impl<'a, T: 'a> DoubleEndedIterator for Children<'a, T> {
216216
}
217217
}
218218

219+
/// Iterator over mutable children.
220+
#[derive(Debug)]
221+
pub struct ChildrenMut<'a, T: 'a> {
222+
tree: &'a mut Tree<T>,
223+
front: Option<NodeId>,
224+
back: Option<NodeId>,
225+
}
226+
impl<'a, T: 'a> FusedIterator for ChildrenMut<'a, T> {}
227+
impl<'a, T: 'a> Iterator for ChildrenMut<'a, T> {
228+
type Item = NodeMut<'a, T>;
229+
fn next(&mut self) -> Option<Self::Item> {
230+
// lifetime cast here is safe because &mut self living shorter than 'a
231+
let tree = unsafe { &mut *(self.tree as *mut Tree<T>) };
232+
if self.front == self.back {
233+
let node = self.front.take().and_then(|x| tree.get_mut(x));
234+
self.back = None;
235+
node
236+
} else {
237+
let mut node = self.front.take().and_then(|x| tree.get_mut(x));
238+
self.front = node
239+
.as_mut()
240+
.and_then(|x: &mut NodeMut<T>| x.next_sibling())
241+
.map(|x| x.id());
242+
node
243+
}
244+
}
245+
}
246+
impl<'a, T: 'a> DoubleEndedIterator for ChildrenMut<'a, T> {
247+
fn next_back(&mut self) -> Option<Self::Item> {
248+
// lifetime cast here is safe because &mut self living shorter than 'a
249+
let tree = unsafe { &mut *(self.tree as *mut Tree<T>) };
250+
if self.front == self.back {
251+
let node = self.back.take().and_then(|x| tree.get_mut(x));
252+
self.front = None;
253+
node
254+
} else {
255+
let mut node = self.back.take().and_then(|x| tree.get_mut(x));
256+
self.back = node
257+
.as_mut()
258+
.and_then(|x: &mut NodeMut<T>| x.prev_sibling())
259+
.map(|x| x.id());
260+
node
261+
}
262+
}
263+
}
264+
219265
/// Open or close edge of a node.
220266
#[derive(Debug)]
221267
pub enum Edge<'a, T: 'a> {
@@ -354,3 +400,15 @@ impl<'a, T: 'a> NodeRef<'a, T> {
354400
Descendants(self.traverse())
355401
}
356402
}
403+
404+
impl<'a, T: 'a> NodeMut<'a, T> {
405+
/// Returns an iterator over mutable children.
406+
pub fn children_mut<'b>(&'b mut self) -> ChildrenMut<'b, T> {
407+
let (front, back) = self.node().children.unzip();
408+
ChildrenMut {
409+
tree: self.tree,
410+
front,
411+
back,
412+
}
413+
}
414+
}

tests/iter.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,55 @@ fn last_children() {
164164
);
165165
}
166166

167+
#[test]
168+
fn children_mut() {
169+
let mut tree = tree!( 1 => { 2, 3, 4 } );
170+
for (num, mut child) in tree.root_mut().children_mut().enumerate() {
171+
*child.value() += 10 + num;
172+
}
173+
assert_eq!(
174+
vec![&12, &14, &16],
175+
tree.root()
176+
.children()
177+
.map(|n| n.value())
178+
.collect::<Vec<_>>()
179+
);
180+
}
181+
182+
#[test]
183+
fn children_mut_fused() {
184+
let mut tree = tree!( 1 => { 2, 3, 4 } );
185+
let mut root = tree.root_mut();
186+
let mut children_mut = root.children_mut();
187+
for mut child in children_mut.by_ref() {
188+
*child.value() += 10;
189+
}
190+
191+
assert!(children_mut.next().is_none());
192+
assert_eq!(
193+
vec![&12, &13, &14],
194+
tree.root()
195+
.children()
196+
.map(|n| n.value())
197+
.collect::<Vec<_>>()
198+
);
199+
}
200+
201+
#[test]
202+
fn children_mut_rev() {
203+
let mut tree = tree!( 1 => { 2, 3, 4 } );
204+
for (num, mut child) in tree.root_mut().children_mut().rev().enumerate() {
205+
*child.value() += 10 + num;
206+
}
207+
assert_eq!(
208+
vec![&14, &14, &14],
209+
tree.root()
210+
.children()
211+
.map(|n| n.value())
212+
.collect::<Vec<_>>()
213+
);
214+
}
215+
167216
#[test]
168217
fn traverse() {
169218
use ego_tree::iter::Edge;

0 commit comments

Comments
 (0)