So i'm trying out to build a tree data structure in rust and i find it difficult to wrap my head around how to implement the IntoIterator
trait.
I started our with using the example given here in the rust docs for Rc
std::rc - Rust
I then started to try that wrap this structure in structs etc. So that i didn't have to work with Rc
and RefCell
etc directly.
It all went quite well until i needed to implement Iterator
and IntoIterator
for the children
. I wanted to use a for loop to iterate over references and i have no idea how to write it.
this is my code:
#[derive(Debug, Default)]
struct Nodes(RefCell<Vec<Weak<NodeInner>>>);
impl Iterator for Nodes {
type Item = Weak<NodeInner>;
fn next(&mut self) -> Option<Self::Item> {
self.0.borrow().into_iter().next()
}
}
#[derive(Debug, Default)]
struct Node {
inner: Rc<NodeInner>,
}
impl Node {
fn new(parent: Option<Node>, children: Nodes, point: Point) -> Self {
Self {
inner: Rc::new(NodeInner {
parent,
children,
point,
}),
}
}
fn from_inner(inner: Rc<NodeInner>) -> Node {
Self { inner }
}
fn push(&self, node: &Node) {
self.inner.children.0.borrow_mut().push(Rc::downgrade(node))
}
}
impl Deref for Node {
type Target = Rc<NodeInner>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl Clone for Node {
fn clone(&self) -> Self {
Self {
inner: Rc::clone(&self.inner),
}
}
}
#[derive(Debug, Default)]
struct Point {
x: u32,
y: u32,
}
#[derive(Debug, Default)]
struct NodeInner {
parent: Option<Node>,
children: Nodes,
point: Point,
}
struct NodeBuilder {
parent: Option<Node>,
children: Nodes,
point: Point,
}
impl NodeBuilder {
fn new(point: Point) -> NodeBuilder {
Self {
parent: None,
children: Nodes(RefCell::new(vec![])),
point,
}
}
fn with_parent(mut self, node: &Node) -> NodeBuilder {
self.parent = Some(node.clone());
self
}
fn build(self) -> Node {
Node::new(self.parent, self.children, self.point)
}
}
fn main() {
let parent: Node = NodeBuilder::new(Point { x: 0, y: 0 }).build();
let child_1: Node = NodeBuilder::new(Point { x: 1, y: 0 })
.with_parent(&parent)
.build();
let child_2: Node = NodeBuilder::new(Point { x: 0, y: 1 })
.with_parent(&parent)
.build();
parent.push(&child_1);
parent.push(&child_2);
// This doesnt work
for child in &parent.children {
println!("x: {}, y: {}", child.point.x, child.point.y);
}
}
The example provided wraps the children
in a Vec<T>
that is placed in a RefCell<T>
.
What i dont really get is:
- Does
IntoIterator
consume the collection? - Do i need to implement
Iterator
and then use theIter
function when implementingIntoIterator
- How do i implement
Iter_mut
? - Can you implement all of this if the collection is in a
RefCell
or do i actually need to owned values? - Is there any way to not return
Weak<NodeInner>
and instead pureNode
?
im pretty confused here because the docs specifically just talks about the trait Iterator
and just a simple nested Vec<T>