Petgraph implements all its traits for references to it's internal graph type. How can I store and use a Graph
rather than an &Graph
in a struct?
This works but stores a reference to the graph:
extern crate petgraph;
use crate::petgraph::visit::*;
use petgraph::data::*;
use petgraph::*;
struct StateMachine<G>
where
G: GraphBase,
{
state_network: G,
state: <G as GraphBase>::NodeId,
}
impl<G> StateMachine<G>
where
G: IntoNodeReferences
+ IntoEdgeReferences
+ IntoEdges
+ Data
+ NodeIndexable
+ GraphProp
+ DataMap
+ GraphBase,
<G as Data>::NodeWeight: Eq + Copy,
<G as Data>::EdgeWeight: Eq + Copy,
{
pub fn next(&mut self, input: <G as Data>::EdgeWeight) -> Option<<G as Data>::NodeWeight> {
for edge in self.state_network.edges(self.state) {
if *edge.weight() == input {
self.state = edge.target();
return match self.state_network.node_weight(self.state) {
Option::Some(weight) => Some(*weight),
Option::None => Option::None,
};
}
}
return Option::None;
}
pub fn new(network: G, start: <G as Data>::NodeWeight) -> Option<StateMachine<G>> {
for nr in network.node_references() {
if *(network.node_weight(nr.id())).unwrap() == start {
return Option::Some(StateMachine {
state_network: network,
state: nr.id(),
});
}
}
return Option::None;
}
}
fn main() {
let mut sn: Graph<&str, u32, petgraph::Directed> = Graph::new();
let sn_item1 = sn.add_node("a");
let sn_item2 = sn.add_node("b");
let sn_item3 = sn.add_node("c");
let sn_item4 = sn.add_node("d");
let sn_item5 = sn.add_node("e");
sn.add_edge(sn_item1, sn_item2, 1);
sn.add_edge(sn_item1, sn_item3, 2);
sn.add_edge(sn_item2, sn_item4, 1);
sn.add_edge(sn_item2, sn_item5, 2);
sn.add_edge(sn_item5, sn_item1, 2);
sn.add_edge(sn_item5, sn_item3, 1);
let mut sm = StateMachine::new(&sn, "a").unwrap();
println!("{}", sm.next(1).unwrap());
}
But storing the Graph directly doesn't work
extern crate petgraph;
use crate::petgraph::visit::*;
use petgraph::data::*;
use petgraph::*;
struct StateMachine<'a, G>
where
&'a G: GraphBase,
{
state_network: G,
state: <&'a G as GraphBase>::NodeId,
}
impl<'a, G> StateMachine<'a, G>
where
&'a G: IntoNodeReferences
+ IntoEdgeReferences
+ IntoEdges
+ Data
+ NodeIndexable
+ GraphProp
+ DataMap
+ GraphBase,
<&'a G as Data>::NodeWeight: Eq + Copy,
<&'a G as Data>::EdgeWeight: Eq + Copy,
{
pub fn next(&mut self, input: <&'a G as Data>::EdgeWeight) -> Option<<&'a G as Data>::NodeWeight> {
for edge in (&self.state_network).edges(self.state) {
if *edge.weight() == input {
self.state = edge.target();
return match (&self.state_network).node_weight(self.state) {
Option::Some(weight) => Some(*weight),
Option::None => Option::None,
};
}
}
return Option::None;
}
pub fn new(network: G, start: <&'a G as Data>::NodeWeight) -> Option<StateMachine<'a, G>> {
for nr in network.node_references() {
if *((&network).node_weight(nr.id())).unwrap() == start {
return Option::Some(StateMachine {
state_network: network,
state: nr.id(),
});
}
}
return Option::None;
}
}
fn main() {
let mut sn: Graph<&str, u32, petgraph::Directed> = Graph::new();
let sn_item1 = sn.add_node("a");
let sn_item2 = sn.add_node("b");
let sn_item3 = sn.add_node("c");
let sn_item4 = sn.add_node("d");
let sn_item5 = sn.add_node("e");
sn.add_edge(sn_item1, sn_item2, 1);
sn.add_edge(sn_item1, sn_item3, 2);
sn.add_edge(sn_item2, sn_item4, 1);
sn.add_edge(sn_item2, sn_item5, 2);
sn.add_edge(sn_item5, sn_item1, 2);
sn.add_edge(sn_item5, sn_item3, 1);
let mut sm = StateMachine::new(sn, "a").unwrap();
println!("{}", sm.next(1).unwrap());
}
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:29:21
|
29 | for edge in (&self.state_network).edges(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 28:5...
--> src/main.rs:28:5
|
28 | / pub fn next(&mut self, input: <&'a G as Data>::EdgeWeight) -> Option<<&'a G as Data>::NodeWeight> {
29 | | for edge in (&self.state_network).edges(self.state) {
30 | | if *edge.weight() == input {
31 | | self.state = edge.target();
... |
38 | | return Option::None;
39 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:29:21
|
29 | for edge in (&self.state_network).edges(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 15:6...
--> src/main.rs:15:6
|
15 | impl<'a, G> StateMachine<'a, G>
| ^^
= note: ...so that the expression is assignable:
expected <&G as petgraph::visit::GraphBase>::NodeId
found <&'a G as petgraph::visit::GraphBase>::NodeId
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:32:30
|
32 | return match (&self.state_network).node_weight(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 28:5...
--> src/main.rs:28:5
|
28 | / pub fn next(&mut self, input: <&'a G as Data>::EdgeWeight) -> Option<<&'a G as Data>::NodeWeight> {
29 | | for edge in (&self.state_network).edges(self.state) {
30 | | if *edge.weight() == input {
31 | | self.state = edge.target();
... |
38 | | return Option::None;
39 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:32:30
|
32 | return match (&self.state_network).node_weight(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 15:6...
--> src/main.rs:15:6
|
15 | impl<'a, G> StateMachine<'a, G>
| ^^
= note: ...so that the expression is assignable:
expected <&G as petgraph::visit::GraphBase>::NodeId
found <&'a G as petgraph::visit::GraphBase>::NodeId
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0495`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.