So I am trying to make my own octree in Rust, but I'm having trouble with my set
function. It's supposed to be recursive, and there is a point where I am matching the child node. Except, it has two errors:
Octree
holds references to child Octree
s, if I try to set the reference to a new one, it will drop the value.I am kinda at a loss. Do I need to create a trait and then create types for the root, branches, and leaves? Or is there a way to save my code?
Code that breaks:
match self.children[index] { // Here it says I can't borrow it
Some(ref mut child) => {
child.set(pos, val);
},
None => {
let mut new_pos = self.pos.clone();
let new_size = self.size.clone() as i32/2 ;
match index {
0 => { new_pos[0] -= new_size.clone(); new_pos[0] -= new_size.clone(); new_pos[0] -= new_size.clone(); },
1 => { new_pos[0] -= new_size.clone(); new_pos[0] -= new_size.clone(); new_pos[0] += new_size.clone(); },
2 => { new_pos[0] -= new_size.clone(); new_pos[0] += new_size.clone(); new_pos[0] -= new_size.clone(); },
3 => { new_pos[0] -= new_size.clone(); new_pos[0] += new_size.clone(); new_pos[0] += new_size.clone(); },
4 => { new_pos[0] += new_size.clone(); new_pos[0] -= new_size.clone(); new_pos[0] -= new_size.clone(); },
5 => { new_pos[0] += new_size.clone(); new_pos[0] -= new_size.clone(); new_pos[0] += new_size.clone(); },
6 => { new_pos[0] += new_size.clone(); new_pos[0] += new_size.clone(); new_pos[0] -= new_size.clone(); },
7 => { new_pos[0] += new_size.clone(); new_pos[0] += new_size.clone(); new_pos[0] += new_size.clone(); }
_ => { panic!("Index out of bounds"); }
}
let mut new_tree = Octree::new(new_size.clone() as u8, new_pos);
new_tree.set(pos, val);
*self.children[index] = Some(new_tree); // Here it says I can't write to it
}
}
References are also known as borrows; their main purpose is to get temporary, “borrowed” access to a value that is owned by something else.
When you are defining a data structure, it should almost never contain references; instead, should use owned types. Sometimes this means writing T
instead of &'a T
; in this case, since the structure is recursive, it needs a pointer, but an owning one rather than a borrowing one — i.e. Box
.
Change your structure definition from
pub struct Octree<'a, T> {
children: [&'a Option<Octree<'a, T>>; 8],
data: Option<T>,
size: u8,
pos: VecI3
}
to
pub struct Octree<T> {
children: [Option<Box<Octree<T>>>; 8],
data: Option<T>,
size: u8,
pos: VecI3
}
Notice that the structure no longer has a lifetime parameter — just as, for example, BTreeMap
(a recursive structure in the standard library) does not.
Then to insert a child node you will need to use:
*self.children[index] = Some(Box::new(new_tree));