use indexmap::IndexMap;
use netrun_sim::graph::{
Edge, Graph, MaxSalvos, Node, PacketCount, Port, PortRef, PortSlotSpec, PortState, PortType,
SalvoCondition, SalvoConditionTerm,
};
use netrun_sim::net::{
NetAction, NetActionResponse, NetActionResponseData, NetSim, PacketLocation,
};
use std::collections::HashMap;
fn main() {
let graph = create_linear_graph();
println!("Created graph with {} nodes", graph.nodes().len());
let mut net = NetSim::new(graph);
let packet_id = match net.do_action(&NetAction::CreatePacket(None)) {
NetActionResponse::Success(NetActionResponseData::Packet(id), _) => {
println!("Created packet: {}", id);
id
}
_ => panic!("Failed to create packet"),
};
let edge_a_b = PacketLocation::Edge(Edge {
source: PortRef {
node_name: "A".to_string(),
port_type: PortType::Output,
port_name: "out".to_string(),
},
target: PortRef {
node_name: "B".to_string(),
port_type: PortType::Input,
port_name: "in".to_string(),
},
});
net.do_action(&NetAction::TransportPacketToLocation(
packet_id.clone(),
edge_a_b,
));
println!("Placed packet on edge A -> B");
net.run_until_blocked();
println!("Ran network until blocked");
let startable = net.get_startable_epochs();
println!("Startable epochs: {}", startable.len());
if let Some(epoch_id) = startable.first() {
match net.do_action(&NetAction::StartEpoch(epoch_id.clone())) {
NetActionResponse::Success(NetActionResponseData::StartedEpoch(epoch), _) => {
println!("Started epoch {} on node {}", epoch.id, epoch.node_name);
net.do_action(&NetAction::ConsumePacket(packet_id));
println!("Consumed input packet");
let output_packet =
match net.do_action(&NetAction::CreatePacket(Some(epoch.id.clone()))) {
NetActionResponse::Success(NetActionResponseData::Packet(id), _) => id,
_ => panic!("Failed to create output packet"),
};
println!("Created output packet: {}", output_packet);
net.do_action(&NetAction::LoadPacketIntoOutputPort(
output_packet.clone(),
"out".to_string(),
));
println!("Loaded packet into output port");
net.do_action(&NetAction::SendOutputSalvo(
epoch.id.clone(),
"default".to_string(),
));
println!("Sent output salvo - packet is now on edge B -> C");
net.do_action(&NetAction::FinishEpoch(epoch.id));
println!("Finished epoch");
net.run_until_blocked();
println!("Ran network until blocked again");
let startable_c = net.get_startable_epochs();
println!(
"New startable epochs (should be at C): {}",
startable_c.len()
);
}
_ => panic!("Failed to start epoch"),
}
}
println!("\nLinear flow example complete!");
}
fn create_linear_graph() -> Graph {
let nodes = vec![
create_node("A", vec![], vec!["out"]),
create_node("B", vec!["in"], vec!["out"]),
create_node("C", vec!["in"], vec![]),
];
let edges = vec![
create_edge("A", "out", "B", "in"),
create_edge("B", "out", "C", "in"),
];
let graph = Graph::new(nodes, edges);
assert!(graph.validate().is_empty(), "Graph validation failed");
graph
}
fn create_node(name: &str, in_ports: Vec<&str>, out_ports: Vec<&str>) -> Node {
let in_ports_map: HashMap<String, Port> = in_ports
.iter()
.map(|p| {
(
p.to_string(),
Port {
slots_spec: PortSlotSpec::Infinite,
},
)
})
.collect();
let out_ports_map: HashMap<String, Port> = out_ports
.iter()
.map(|p| {
(
p.to_string(),
Port {
slots_spec: PortSlotSpec::Infinite,
},
)
})
.collect();
let mut in_salvo_conditions = IndexMap::new();
if !in_ports.is_empty() {
in_salvo_conditions.insert(
"default".to_string(),
SalvoCondition {
max_salvos: MaxSalvos::Finite(1),
ports: in_ports
.iter()
.map(|s| (s.to_string(), PacketCount::All))
.collect(),
term: SalvoConditionTerm::Port {
port_name: in_ports[0].to_string(),
state: PortState::NonEmpty,
},
},
);
}
let mut out_salvo_conditions = IndexMap::new();
if !out_ports.is_empty() {
out_salvo_conditions.insert(
"default".to_string(),
SalvoCondition {
max_salvos: MaxSalvos::Infinite,
ports: out_ports
.iter()
.map(|s| (s.to_string(), PacketCount::All))
.collect(),
term: SalvoConditionTerm::Port {
port_name: out_ports[0].to_string(),
state: PortState::NonEmpty,
},
},
);
}
Node {
name: name.to_string(),
in_ports: in_ports_map,
out_ports: out_ports_map,
in_salvo_conditions,
out_salvo_conditions,
dependency_request_config: None,
}
}
fn create_edge(src_node: &str, src_port: &str, tgt_node: &str, tgt_port: &str) -> Edge {
Edge {
source: PortRef {
node_name: src_node.to_string(),
port_type: PortType::Output,
port_name: src_port.to_string(),
},
target: PortRef {
node_name: tgt_node.to_string(),
port_type: PortType::Input,
port_name: tgt_port.to_string(),
},
}
}