1use netrun_sim::graph::{
11 Edge, Graph, Node, Port, PortRef, PortSlotSpec, PortState, PortType,
12 SalvoCondition, SalvoConditionTerm,
13};
14use netrun_sim::net::{
15 Net, NetAction, NetActionResponse, NetActionResponseData, PacketLocation,
16};
17use std::collections::HashMap;
18
19fn main() {
20 let graph = create_linear_graph();
22 println!("Created graph with {} nodes", graph.nodes().len());
23
24 let mut net = Net::new(graph);
26
27 let packet_id = match net.do_action(&NetAction::CreatePacket(None)) {
29 NetActionResponse::Success(NetActionResponseData::Packet(id), _) => {
30 println!("Created packet: {}", id);
31 id
32 }
33 _ => panic!("Failed to create packet"),
34 };
35
36 let edge_a_b = PacketLocation::Edge(Edge {
38 source: PortRef {
39 node_name: "A".to_string(),
40 port_type: PortType::Output,
41 port_name: "out".to_string(),
42 },
43 target: PortRef {
44 node_name: "B".to_string(),
45 port_type: PortType::Input,
46 port_name: "in".to_string(),
47 },
48 });
49 net.do_action(&NetAction::TransportPacketToLocation(packet_id.clone(), edge_a_b));
50 println!("Placed packet on edge A -> B");
51
52 net.do_action(&NetAction::RunNetUntilBlocked);
54 println!("Ran network until blocked");
55
56 let startable = net.get_startable_epochs();
58 println!("Startable epochs: {}", startable.len());
59
60 if let Some(epoch_id) = startable.first() {
61 match net.do_action(&NetAction::StartEpoch(epoch_id.clone())) {
63 NetActionResponse::Success(NetActionResponseData::StartedEpoch(epoch), _) => {
64 println!("Started epoch {} on node {}", epoch.id, epoch.node_name);
65
66 net.do_action(&NetAction::ConsumePacket(packet_id));
71 println!("Consumed input packet");
72
73 let output_packet = match net.do_action(&NetAction::CreatePacket(Some(epoch.id.clone()))) {
75 NetActionResponse::Success(NetActionResponseData::Packet(id), _) => id,
76 _ => panic!("Failed to create output packet"),
77 };
78 println!("Created output packet: {}", output_packet);
79
80 net.do_action(&NetAction::LoadPacketIntoOutputPort(output_packet.clone(), "out".to_string()));
82 println!("Loaded packet into output port");
83
84 net.do_action(&NetAction::SendOutputSalvo(epoch.id.clone(), "default".to_string()));
86 println!("Sent output salvo - packet is now on edge B -> C");
87
88 net.do_action(&NetAction::FinishEpoch(epoch.id));
90 println!("Finished epoch");
91
92 net.do_action(&NetAction::RunNetUntilBlocked);
94 println!("Ran network until blocked again");
95
96 let startable_c = net.get_startable_epochs();
98 println!("New startable epochs (should be at C): {}", startable_c.len());
99 }
100 _ => panic!("Failed to start epoch"),
101 }
102 }
103
104 println!("\nLinear flow example complete!");
105}
106
107fn create_linear_graph() -> Graph {
109 let nodes = vec![
110 create_node("A", vec![], vec!["out"]),
111 create_node("B", vec!["in"], vec!["out"]),
112 create_node("C", vec!["in"], vec![]),
113 ];
114
115 let edges = vec![
116 create_edge("A", "out", "B", "in"),
117 create_edge("B", "out", "C", "in"),
118 ];
119
120 let graph = Graph::new(nodes, edges);
121 assert!(graph.validate().is_empty(), "Graph validation failed");
122 graph
123}
124
125fn create_node(name: &str, in_ports: Vec<&str>, out_ports: Vec<&str>) -> Node {
126 let in_ports_map: HashMap<String, Port> = in_ports
127 .iter()
128 .map(|p| (p.to_string(), Port { slots_spec: PortSlotSpec::Infinite }))
129 .collect();
130
131 let out_ports_map: HashMap<String, Port> = out_ports
132 .iter()
133 .map(|p| (p.to_string(), Port { slots_spec: PortSlotSpec::Infinite }))
134 .collect();
135
136 let mut in_salvo_conditions = HashMap::new();
138 if !in_ports.is_empty() {
139 in_salvo_conditions.insert(
140 "default".to_string(),
141 SalvoCondition {
142 max_salvos: 1,
143 ports: in_ports.iter().map(|s| s.to_string()).collect(),
144 term: SalvoConditionTerm::Port {
145 port_name: in_ports[0].to_string(),
146 state: PortState::NonEmpty,
147 },
148 },
149 );
150 }
151
152 let mut out_salvo_conditions = HashMap::new();
154 if !out_ports.is_empty() {
155 out_salvo_conditions.insert(
156 "default".to_string(),
157 SalvoCondition {
158 max_salvos: 0, ports: out_ports.iter().map(|s| s.to_string()).collect(),
160 term: SalvoConditionTerm::Port {
161 port_name: out_ports[0].to_string(),
162 state: PortState::NonEmpty,
163 },
164 },
165 );
166 }
167
168 Node {
169 name: name.to_string(),
170 in_ports: in_ports_map,
171 out_ports: out_ports_map,
172 in_salvo_conditions,
173 out_salvo_conditions,
174 }
175}
176
177fn create_edge(src_node: &str, src_port: &str, tgt_node: &str, tgt_port: &str) -> Edge {
178 Edge {
179 source: PortRef {
180 node_name: src_node.to_string(),
181 port_type: PortType::Output,
182 port_name: src_port.to_string(),
183 },
184 target: PortRef {
185 node_name: tgt_node.to_string(),
186 port_type: PortType::Input,
187 port_name: tgt_port.to_string(),
188 },
189 }
190}