I am trying to rewrite a self-referential(edges and nodes) graph(C++ code) into Rust Playground
There are 3 base structs
struct HalfEdge<'a, NodeData, EdgeData, DerivedNode, DerivedEdge> {
node_data: PhantomData<NodeData>,
data: EdgeData,
twin: Option<&'a mut DerivedEdge>,
next: Option<&'a mut DerivedEdge>,
prev: Option<&'a mut DerivedEdge>,
from: Option<&'a mut DerivedNode>,
to: Option<&'a mut DerivedNode>,
}
struct HalfEdgeNode<NodeData, EdgeData, DerivedNode, DerivedEdge> {
data: NodeData,
edge_data: PhantomData<EdgeData>,
derive_node: Option<DerivedNode>,
incident_edge: Option<DerivedEdge>,
}
struct HalfEdgeGraph<NodeData, EdgeData, DerivedNode, DerivedEdge> {
_node_data: PhantomData<NodeData>,
_edge_data: PhantomData<EdgeData>,
nodes: Vec<DerivedNode>,
edges: Vec<DerivedEdge>,
}
And the corresponding concrete structs
struct STHalfEdge<'a>(
HalfEdge<
'a,
SkeletalTrapezoidationJoint,
SkeletalTrapezoidationEdge,
STHalfEdgeNode<'a>,
Box<STHalfEdge<'a>>,
>,
);
struct STHalfEdgeNode<'a>(
HalfEdgeNode<
SkeletalTrapezoidationJoint,
SkeletalTrapezoidationEdge,
Box<STHalfEdgeNode<'a>>,
Box<STHalfEdge<'a>>,
>,
);
struct SkeletalTrapezoidationGraph<'a>(
HalfEdgeGraph<
SkeletalTrapezoidationJoint,
SkeletalTrapezoidationEdge,
STHalfEdgeNode<'a>,
STHalfEdge<'a>,
>,
);
Although the translation from the OOP approach to Rust is not ideal, I managed to proceed with the rewrite, until I hit this for loop, particularly twin = twin->prev_->twin_->prev_
for (edge_t* twin = source_twin;; twin = twin->prev_->twin_->prev_)
{
edge_t* edge = &graph_.edges.front();
edge->from_ = twin->to_;
edge->to_ = twin->from_;
edge->twin_ = twin;
twin->twin_ = edge;
edge->from_->incident_edge_ = edge;
}
I deducted it is equivalent as below in Rust
let mut twin: Option<&mut STHalfEdge> = source_twin;
loop {
// forgive me for the as_mut() and unwrap()
let t: &mut Box<STHalfEdge> = twin
.as_mut()
.unwrap()
.0
.prev
.as_mut()
.unwrap()
.0
.twin
.as_mut()
.unwrap()
.0
.prev
.as_mut()
.unwrap();
twin = Some(&mut *t);
}
Because it is a self-referential struct, things are really ugly now.
error[E0506]: cannot assign to `twin` because it is borrowed
--> src/lib.rs:179:17
|
164 | let t: &mut Box<STHalfEdge> = twin
| ---- `twin` is borrowed here
...
179 | twin = Some(&mut *t);
| ^^^^^^^^^^^^^^^^^^^^
| |
| `twin` is assigned to here but it was already borrowed
| borrow later used here
How should I tackle this problem?