use std::collections::BTreeSet;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NodeId(pub usize);
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum NodePrimitive {
Run,
All,
Race,
Map,
Spawn,
SpawnAndWait,
Receive,
Sleep,
StartTimer,
CancelTimer,
Branch,
Opaque,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum CorrelationKey {
ActivitySequence {
ordinal: usize,
activity: String,
},
Signal {
reference: String,
},
Timer {
id: String,
},
Child {
ordinal: usize,
name: String,
},
ControlFlow {
ordinal: usize,
},
Opaque {
ordinal: usize,
snippet: String,
},
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct GraphNode {
pub id: NodeId,
pub primitive: NodePrimitive,
pub correlation: CorrelationKey,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ArmLabel {
Ok,
Error,
Wildcard,
Pattern(String),
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum EdgeKind {
Sequence,
Branch {
arm: ArmLabel,
},
FanOut,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct GraphEdge {
pub from: NodeId,
pub to: NodeId,
pub kind: EdgeKind,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct WorkflowGraph {
pub entry_module: String,
pub nodes: Vec<GraphNode>,
pub edges: Vec<GraphEdge>,
}
impl WorkflowGraph {
#[must_use]
pub fn entry_module(&self) -> &str {
&self.entry_module
}
#[must_use]
pub fn nodes(&self) -> &[GraphNode] {
&self.nodes
}
#[must_use]
pub fn edges(&self) -> &[GraphEdge] {
&self.edges
}
#[must_use]
pub fn node(&self, id: NodeId) -> Option<&GraphNode> {
self.nodes.iter().find(|node| node.id == id)
}
#[must_use]
pub fn structurally_equals(&self, other: &Self) -> bool {
if self.entry_module != other.entry_module {
return false;
}
let self_nodes: BTreeSet<(NodeId, NodePrimitive, CorrelationKey)> = self
.nodes
.iter()
.map(|node| (node.id, node.primitive, node.correlation.clone()))
.collect();
let other_nodes: BTreeSet<(NodeId, NodePrimitive, CorrelationKey)> = other
.nodes
.iter()
.map(|node| (node.id, node.primitive, node.correlation.clone()))
.collect();
if self_nodes != other_nodes {
return false;
}
let self_edges: BTreeSet<GraphEdge> = self.edges.iter().cloned().collect();
let other_edges: BTreeSet<GraphEdge> = other.edges.iter().cloned().collect();
self_edges == other_edges
}
}