Net

Struct Net 

Source
pub struct Net {
    pub graph: Graph,
    /* private fields */
}
Expand description

The runtime state of a flow-based network.

A Net is created from a Graph and tracks:

  • All packets and their locations
  • All epochs and their states
  • Which epochs are startable

All mutations must go through Net::do_action to ensure proper event tracking.

Fields§

§graph: Graph

The graph topology this network is running on.

Implementations§

Source§

impl Net

Source

pub fn new(graph: Graph) -> Self

Creates a new Net from a Graph.

Initializes packet location tracking for all edges and input ports.

Examples found in repository?
examples/diamond_flow.rs (line 30)
24fn main() {
25    // Create a diamond graph
26    let graph = create_diamond_graph();
27    println!("Created diamond graph: A -> B,C -> D");
28    println!("D requires inputs from BOTH B and C\n");
29
30    let mut net = Net::new(graph);
31
32    // Create two packets and place them on edges from A
33    let packet1 = create_packet(&mut net);
34    let packet2 = create_packet(&mut net);
35    println!("Created packets: {} and {}", packet1, packet2);
36
37    // Place packet1 on edge A -> B
38    let edge_a_b = edge_location("A", "out1", "B", "in");
39    net.do_action(&NetAction::TransportPacketToLocation(packet1.clone(), edge_a_b));
40    println!("Placed packet1 on edge A -> B");
41
42    // Place packet2 on edge A -> C
43    let edge_a_c = edge_location("A", "out2", "C", "in");
44    net.do_action(&NetAction::TransportPacketToLocation(packet2.clone(), edge_a_c));
45    println!("Placed packet2 on edge A -> C");
46
47    // Run network - packets move to B and C, triggering epochs
48    net.do_action(&NetAction::RunNetUntilBlocked);
49
50    let startable = net.get_startable_epochs();
51    println!("\nAfter first run: {} startable epochs (B and C)", startable.len());
52
53    // Process B and C, sending outputs to D
54    for epoch_id in startable {
55        let epoch = net.get_epoch(&epoch_id).unwrap();
56        let node_name = epoch.node_name.clone();
57        println!("\nProcessing node {}", node_name);
58
59        // Start the epoch
60        let started = match net.do_action(&NetAction::StartEpoch(epoch_id.clone())) {
61            NetActionResponse::Success(NetActionResponseData::StartedEpoch(e), _) => e,
62            _ => panic!("Failed to start epoch"),
63        };
64
65        // Find and consume the input packet
66        let input_packet = started.in_salvo.packets[0].1.clone();
67        net.do_action(&NetAction::ConsumePacket(input_packet));
68
69        // Create output packet
70        let output = create_packet_in_epoch(&mut net, &started.id);
71
72        // Load into output port and send
73        net.do_action(&NetAction::LoadPacketIntoOutputPort(output, "out".to_string()));
74        net.do_action(&NetAction::SendOutputSalvo(started.id.clone(), "default".to_string()));
75
76        // Finish epoch
77        net.do_action(&NetAction::FinishEpoch(started.id));
78        println!("  Finished {} - sent packet to D", node_name);
79    }
80
81    // Run network - packets move from B->D and C->D edges to D's input ports
82    net.do_action(&NetAction::RunNetUntilBlocked);
83
84    // Check D's input ports
85    let d_in1 = PacketLocation::InputPort("D".to_string(), "in1".to_string());
86    let d_in2 = PacketLocation::InputPort("D".to_string(), "in2".to_string());
87    println!("\nD's input ports:");
88    println!("  in1 (from B): {} packets", net.packet_count_at(&d_in1));
89    println!("  in2 (from C): {} packets", net.packet_count_at(&d_in2));
90
91    // D should now have a startable epoch (both inputs present)
92    let startable_d = net.get_startable_epochs();
93    println!("\nStartable epochs at D: {}", startable_d.len());
94
95    if let Some(d_epoch_id) = startable_d.first() {
96        let d_epoch = net.get_epoch(d_epoch_id).unwrap();
97        println!("D's epoch received {} packets from both branches!", d_epoch.in_salvo.packets.len());
98    }
99
100    println!("\nDiamond flow example complete!");
101}
More examples
Hide additional examples
examples/linear_flow.rs (line 25)
19fn main() {
20    // Create a linear graph: A -> B -> C
21    let graph = create_linear_graph();
22    println!("Created graph with {} nodes", graph.nodes().len());
23
24    // Create a network from the graph
25    let mut net = Net::new(graph);
26
27    // Create a packet outside the network
28    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    // Transport packet to the edge A -> B
37    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    // Run the network - packet moves to B's input port and triggers an epoch
53    net.do_action(&NetAction::RunNetUntilBlocked);
54    println!("Ran network until blocked");
55
56    // Check for startable epochs
57    let startable = net.get_startable_epochs();
58    println!("Startable epochs: {}", startable.len());
59
60    if let Some(epoch_id) = startable.first() {
61        // Start the epoch
62        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                // In a real scenario, external code would process the packet here
67                // For this example, we'll just consume it and create an output
68
69                // Consume the input packet
70                net.do_action(&NetAction::ConsumePacket(packet_id));
71                println!("Consumed input packet");
72
73                // Create an output packet
74                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                // Load it into the output port
81                net.do_action(&NetAction::LoadPacketIntoOutputPort(output_packet.clone(), "out".to_string()));
82                println!("Loaded packet into output port");
83
84                // Send the output salvo
85                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                // Finish the epoch
89                net.do_action(&NetAction::FinishEpoch(epoch.id));
90                println!("Finished epoch");
91
92                // Run the network again - packet moves to C
93                net.do_action(&NetAction::RunNetUntilBlocked);
94                println!("Ran network until blocked again");
95
96                // Check for new startable epochs at C
97                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}
Source

pub fn do_action(&mut self, action: &NetAction) -> NetActionResponse

Perform an action on the network.

This is the primary way to mutate the network state. All actions produce a response containing either success data and events, or an error.

§Example
use netrun_sim::net::{Net, NetAction, NetActionResponse, NetActionResponseData};
use netrun_sim::graph::{Graph, Node, Port, PortSlotSpec};
use std::collections::HashMap;

let node = Node {
    name: "A".to_string(),
    in_ports: HashMap::new(),
    out_ports: HashMap::new(),
    in_salvo_conditions: HashMap::new(),
    out_salvo_conditions: HashMap::new(),
};
let graph = Graph::new(vec![node], vec![]);
let mut net = Net::new(graph);

// Create a packet outside the network
let response = net.do_action(&NetAction::CreatePacket(None));
match response {
    NetActionResponse::Success(NetActionResponseData::Packet(id), events) => {
        println!("Created packet {}", id);
    }
    _ => panic!("Expected success"),
}
Examples found in repository?
examples/diamond_flow.rs (line 39)
24fn main() {
25    // Create a diamond graph
26    let graph = create_diamond_graph();
27    println!("Created diamond graph: A -> B,C -> D");
28    println!("D requires inputs from BOTH B and C\n");
29
30    let mut net = Net::new(graph);
31
32    // Create two packets and place them on edges from A
33    let packet1 = create_packet(&mut net);
34    let packet2 = create_packet(&mut net);
35    println!("Created packets: {} and {}", packet1, packet2);
36
37    // Place packet1 on edge A -> B
38    let edge_a_b = edge_location("A", "out1", "B", "in");
39    net.do_action(&NetAction::TransportPacketToLocation(packet1.clone(), edge_a_b));
40    println!("Placed packet1 on edge A -> B");
41
42    // Place packet2 on edge A -> C
43    let edge_a_c = edge_location("A", "out2", "C", "in");
44    net.do_action(&NetAction::TransportPacketToLocation(packet2.clone(), edge_a_c));
45    println!("Placed packet2 on edge A -> C");
46
47    // Run network - packets move to B and C, triggering epochs
48    net.do_action(&NetAction::RunNetUntilBlocked);
49
50    let startable = net.get_startable_epochs();
51    println!("\nAfter first run: {} startable epochs (B and C)", startable.len());
52
53    // Process B and C, sending outputs to D
54    for epoch_id in startable {
55        let epoch = net.get_epoch(&epoch_id).unwrap();
56        let node_name = epoch.node_name.clone();
57        println!("\nProcessing node {}", node_name);
58
59        // Start the epoch
60        let started = match net.do_action(&NetAction::StartEpoch(epoch_id.clone())) {
61            NetActionResponse::Success(NetActionResponseData::StartedEpoch(e), _) => e,
62            _ => panic!("Failed to start epoch"),
63        };
64
65        // Find and consume the input packet
66        let input_packet = started.in_salvo.packets[0].1.clone();
67        net.do_action(&NetAction::ConsumePacket(input_packet));
68
69        // Create output packet
70        let output = create_packet_in_epoch(&mut net, &started.id);
71
72        // Load into output port and send
73        net.do_action(&NetAction::LoadPacketIntoOutputPort(output, "out".to_string()));
74        net.do_action(&NetAction::SendOutputSalvo(started.id.clone(), "default".to_string()));
75
76        // Finish epoch
77        net.do_action(&NetAction::FinishEpoch(started.id));
78        println!("  Finished {} - sent packet to D", node_name);
79    }
80
81    // Run network - packets move from B->D and C->D edges to D's input ports
82    net.do_action(&NetAction::RunNetUntilBlocked);
83
84    // Check D's input ports
85    let d_in1 = PacketLocation::InputPort("D".to_string(), "in1".to_string());
86    let d_in2 = PacketLocation::InputPort("D".to_string(), "in2".to_string());
87    println!("\nD's input ports:");
88    println!("  in1 (from B): {} packets", net.packet_count_at(&d_in1));
89    println!("  in2 (from C): {} packets", net.packet_count_at(&d_in2));
90
91    // D should now have a startable epoch (both inputs present)
92    let startable_d = net.get_startable_epochs();
93    println!("\nStartable epochs at D: {}", startable_d.len());
94
95    if let Some(d_epoch_id) = startable_d.first() {
96        let d_epoch = net.get_epoch(d_epoch_id).unwrap();
97        println!("D's epoch received {} packets from both branches!", d_epoch.in_salvo.packets.len());
98    }
99
100    println!("\nDiamond flow example complete!");
101}
102
103fn create_diamond_graph() -> Graph {
104    // Node A: source with two outputs
105    let node_a = Node {
106        name: "A".to_string(),
107        in_ports: HashMap::new(),
108        out_ports: [
109            ("out1".to_string(), Port { slots_spec: PortSlotSpec::Infinite }),
110            ("out2".to_string(), Port { slots_spec: PortSlotSpec::Infinite }),
111        ].into(),
112        in_salvo_conditions: HashMap::new(),
113        out_salvo_conditions: HashMap::new(),
114    };
115
116    // Node B: one input, one output
117    let node_b = create_simple_node("B");
118
119    // Node C: one input, one output
120    let node_c = create_simple_node("C");
121
122    // Node D: TWO inputs (requires both), no outputs
123    let node_d = Node {
124        name: "D".to_string(),
125        in_ports: [
126            ("in1".to_string(), Port { slots_spec: PortSlotSpec::Infinite }),
127            ("in2".to_string(), Port { slots_spec: PortSlotSpec::Infinite }),
128        ].into(),
129        out_ports: HashMap::new(),
130        in_salvo_conditions: [(
131            "default".to_string(),
132            SalvoCondition {
133                max_salvos: 1,
134                ports: vec!["in1".to_string(), "in2".to_string()],
135                // Require BOTH inputs to be non-empty
136                term: SalvoConditionTerm::And(vec![
137                    SalvoConditionTerm::Port {
138                        port_name: "in1".to_string(),
139                        state: PortState::NonEmpty,
140                    },
141                    SalvoConditionTerm::Port {
142                        port_name: "in2".to_string(),
143                        state: PortState::NonEmpty,
144                    },
145                ]),
146            },
147        )].into(),
148        out_salvo_conditions: HashMap::new(),
149    };
150
151    let edges = vec![
152        create_edge("A", "out1", "B", "in"),
153        create_edge("A", "out2", "C", "in"),
154        create_edge("B", "out", "D", "in1"),
155        create_edge("C", "out", "D", "in2"),
156    ];
157
158    let graph = Graph::new(vec![node_a, node_b, node_c, node_d], edges);
159    assert!(graph.validate().is_empty(), "Graph validation failed");
160    graph
161}
162
163fn create_simple_node(name: &str) -> Node {
164    Node {
165        name: name.to_string(),
166        in_ports: [("in".to_string(), Port { slots_spec: PortSlotSpec::Infinite })].into(),
167        out_ports: [("out".to_string(), Port { slots_spec: PortSlotSpec::Infinite })].into(),
168        in_salvo_conditions: [(
169            "default".to_string(),
170            SalvoCondition {
171                max_salvos: 1,
172                ports: vec!["in".to_string()],
173                term: SalvoConditionTerm::Port {
174                    port_name: "in".to_string(),
175                    state: PortState::NonEmpty,
176                },
177            },
178        )].into(),
179        out_salvo_conditions: [(
180            "default".to_string(),
181            SalvoCondition {
182                max_salvos: 0,
183                ports: vec!["out".to_string()],
184                term: SalvoConditionTerm::Port {
185                    port_name: "out".to_string(),
186                    state: PortState::NonEmpty,
187                },
188            },
189        )].into(),
190    }
191}
192
193fn create_edge(src_node: &str, src_port: &str, tgt_node: &str, tgt_port: &str) -> Edge {
194    Edge {
195        source: PortRef {
196            node_name: src_node.to_string(),
197            port_type: PortType::Output,
198            port_name: src_port.to_string(),
199        },
200        target: PortRef {
201            node_name: tgt_node.to_string(),
202            port_type: PortType::Input,
203            port_name: tgt_port.to_string(),
204        },
205    }
206}
207
208fn edge_location(src_node: &str, src_port: &str, tgt_node: &str, tgt_port: &str) -> PacketLocation {
209    PacketLocation::Edge(Edge {
210        source: PortRef {
211            node_name: src_node.to_string(),
212            port_type: PortType::Output,
213            port_name: src_port.to_string(),
214        },
215        target: PortRef {
216            node_name: tgt_node.to_string(),
217            port_type: PortType::Input,
218            port_name: tgt_port.to_string(),
219        },
220    })
221}
222
223fn create_packet(net: &mut Net) -> ulid::Ulid {
224    match net.do_action(&NetAction::CreatePacket(None)) {
225        NetActionResponse::Success(NetActionResponseData::Packet(id), _) => id,
226        _ => panic!("Failed to create packet"),
227    }
228}
229
230fn create_packet_in_epoch(net: &mut Net, epoch_id: &ulid::Ulid) -> ulid::Ulid {
231    match net.do_action(&NetAction::CreatePacket(Some(epoch_id.clone()))) {
232        NetActionResponse::Success(NetActionResponseData::Packet(id), _) => id,
233        _ => panic!("Failed to create packet in epoch"),
234    }
235}
More examples
Hide additional examples
examples/linear_flow.rs (line 28)
19fn main() {
20    // Create a linear graph: A -> B -> C
21    let graph = create_linear_graph();
22    println!("Created graph with {} nodes", graph.nodes().len());
23
24    // Create a network from the graph
25    let mut net = Net::new(graph);
26
27    // Create a packet outside the network
28    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    // Transport packet to the edge A -> B
37    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    // Run the network - packet moves to B's input port and triggers an epoch
53    net.do_action(&NetAction::RunNetUntilBlocked);
54    println!("Ran network until blocked");
55
56    // Check for startable epochs
57    let startable = net.get_startable_epochs();
58    println!("Startable epochs: {}", startable.len());
59
60    if let Some(epoch_id) = startable.first() {
61        // Start the epoch
62        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                // In a real scenario, external code would process the packet here
67                // For this example, we'll just consume it and create an output
68
69                // Consume the input packet
70                net.do_action(&NetAction::ConsumePacket(packet_id));
71                println!("Consumed input packet");
72
73                // Create an output packet
74                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                // Load it into the output port
81                net.do_action(&NetAction::LoadPacketIntoOutputPort(output_packet.clone(), "out".to_string()));
82                println!("Loaded packet into output port");
83
84                // Send the output salvo
85                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                // Finish the epoch
89                net.do_action(&NetAction::FinishEpoch(epoch.id));
90                println!("Finished epoch");
91
92                // Run the network again - packet moves to C
93                net.do_action(&NetAction::RunNetUntilBlocked);
94                println!("Ran network until blocked again");
95
96                // Check for new startable epochs at C
97                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}
Source

pub fn packet_count_at(&self, location: &PacketLocation) -> usize

Get the number of packets at a given location.

Examples found in repository?
examples/diamond_flow.rs (line 88)
24fn main() {
25    // Create a diamond graph
26    let graph = create_diamond_graph();
27    println!("Created diamond graph: A -> B,C -> D");
28    println!("D requires inputs from BOTH B and C\n");
29
30    let mut net = Net::new(graph);
31
32    // Create two packets and place them on edges from A
33    let packet1 = create_packet(&mut net);
34    let packet2 = create_packet(&mut net);
35    println!("Created packets: {} and {}", packet1, packet2);
36
37    // Place packet1 on edge A -> B
38    let edge_a_b = edge_location("A", "out1", "B", "in");
39    net.do_action(&NetAction::TransportPacketToLocation(packet1.clone(), edge_a_b));
40    println!("Placed packet1 on edge A -> B");
41
42    // Place packet2 on edge A -> C
43    let edge_a_c = edge_location("A", "out2", "C", "in");
44    net.do_action(&NetAction::TransportPacketToLocation(packet2.clone(), edge_a_c));
45    println!("Placed packet2 on edge A -> C");
46
47    // Run network - packets move to B and C, triggering epochs
48    net.do_action(&NetAction::RunNetUntilBlocked);
49
50    let startable = net.get_startable_epochs();
51    println!("\nAfter first run: {} startable epochs (B and C)", startable.len());
52
53    // Process B and C, sending outputs to D
54    for epoch_id in startable {
55        let epoch = net.get_epoch(&epoch_id).unwrap();
56        let node_name = epoch.node_name.clone();
57        println!("\nProcessing node {}", node_name);
58
59        // Start the epoch
60        let started = match net.do_action(&NetAction::StartEpoch(epoch_id.clone())) {
61            NetActionResponse::Success(NetActionResponseData::StartedEpoch(e), _) => e,
62            _ => panic!("Failed to start epoch"),
63        };
64
65        // Find and consume the input packet
66        let input_packet = started.in_salvo.packets[0].1.clone();
67        net.do_action(&NetAction::ConsumePacket(input_packet));
68
69        // Create output packet
70        let output = create_packet_in_epoch(&mut net, &started.id);
71
72        // Load into output port and send
73        net.do_action(&NetAction::LoadPacketIntoOutputPort(output, "out".to_string()));
74        net.do_action(&NetAction::SendOutputSalvo(started.id.clone(), "default".to_string()));
75
76        // Finish epoch
77        net.do_action(&NetAction::FinishEpoch(started.id));
78        println!("  Finished {} - sent packet to D", node_name);
79    }
80
81    // Run network - packets move from B->D and C->D edges to D's input ports
82    net.do_action(&NetAction::RunNetUntilBlocked);
83
84    // Check D's input ports
85    let d_in1 = PacketLocation::InputPort("D".to_string(), "in1".to_string());
86    let d_in2 = PacketLocation::InputPort("D".to_string(), "in2".to_string());
87    println!("\nD's input ports:");
88    println!("  in1 (from B): {} packets", net.packet_count_at(&d_in1));
89    println!("  in2 (from C): {} packets", net.packet_count_at(&d_in2));
90
91    // D should now have a startable epoch (both inputs present)
92    let startable_d = net.get_startable_epochs();
93    println!("\nStartable epochs at D: {}", startable_d.len());
94
95    if let Some(d_epoch_id) = startable_d.first() {
96        let d_epoch = net.get_epoch(d_epoch_id).unwrap();
97        println!("D's epoch received {} packets from both branches!", d_epoch.in_salvo.packets.len());
98    }
99
100    println!("\nDiamond flow example complete!");
101}
Source

pub fn get_packets_at_location( &self, location: &PacketLocation, ) -> Vec<PacketID>

Get all packets at a given location.

Source

pub fn get_epoch(&self, epoch_id: &EpochID) -> Option<&Epoch>

Get an epoch by ID.

Examples found in repository?
examples/diamond_flow.rs (line 55)
24fn main() {
25    // Create a diamond graph
26    let graph = create_diamond_graph();
27    println!("Created diamond graph: A -> B,C -> D");
28    println!("D requires inputs from BOTH B and C\n");
29
30    let mut net = Net::new(graph);
31
32    // Create two packets and place them on edges from A
33    let packet1 = create_packet(&mut net);
34    let packet2 = create_packet(&mut net);
35    println!("Created packets: {} and {}", packet1, packet2);
36
37    // Place packet1 on edge A -> B
38    let edge_a_b = edge_location("A", "out1", "B", "in");
39    net.do_action(&NetAction::TransportPacketToLocation(packet1.clone(), edge_a_b));
40    println!("Placed packet1 on edge A -> B");
41
42    // Place packet2 on edge A -> C
43    let edge_a_c = edge_location("A", "out2", "C", "in");
44    net.do_action(&NetAction::TransportPacketToLocation(packet2.clone(), edge_a_c));
45    println!("Placed packet2 on edge A -> C");
46
47    // Run network - packets move to B and C, triggering epochs
48    net.do_action(&NetAction::RunNetUntilBlocked);
49
50    let startable = net.get_startable_epochs();
51    println!("\nAfter first run: {} startable epochs (B and C)", startable.len());
52
53    // Process B and C, sending outputs to D
54    for epoch_id in startable {
55        let epoch = net.get_epoch(&epoch_id).unwrap();
56        let node_name = epoch.node_name.clone();
57        println!("\nProcessing node {}", node_name);
58
59        // Start the epoch
60        let started = match net.do_action(&NetAction::StartEpoch(epoch_id.clone())) {
61            NetActionResponse::Success(NetActionResponseData::StartedEpoch(e), _) => e,
62            _ => panic!("Failed to start epoch"),
63        };
64
65        // Find and consume the input packet
66        let input_packet = started.in_salvo.packets[0].1.clone();
67        net.do_action(&NetAction::ConsumePacket(input_packet));
68
69        // Create output packet
70        let output = create_packet_in_epoch(&mut net, &started.id);
71
72        // Load into output port and send
73        net.do_action(&NetAction::LoadPacketIntoOutputPort(output, "out".to_string()));
74        net.do_action(&NetAction::SendOutputSalvo(started.id.clone(), "default".to_string()));
75
76        // Finish epoch
77        net.do_action(&NetAction::FinishEpoch(started.id));
78        println!("  Finished {} - sent packet to D", node_name);
79    }
80
81    // Run network - packets move from B->D and C->D edges to D's input ports
82    net.do_action(&NetAction::RunNetUntilBlocked);
83
84    // Check D's input ports
85    let d_in1 = PacketLocation::InputPort("D".to_string(), "in1".to_string());
86    let d_in2 = PacketLocation::InputPort("D".to_string(), "in2".to_string());
87    println!("\nD's input ports:");
88    println!("  in1 (from B): {} packets", net.packet_count_at(&d_in1));
89    println!("  in2 (from C): {} packets", net.packet_count_at(&d_in2));
90
91    // D should now have a startable epoch (both inputs present)
92    let startable_d = net.get_startable_epochs();
93    println!("\nStartable epochs at D: {}", startable_d.len());
94
95    if let Some(d_epoch_id) = startable_d.first() {
96        let d_epoch = net.get_epoch(d_epoch_id).unwrap();
97        println!("D's epoch received {} packets from both branches!", d_epoch.in_salvo.packets.len());
98    }
99
100    println!("\nDiamond flow example complete!");
101}
Source

pub fn get_startable_epochs(&self) -> Vec<EpochID>

Get all startable epoch IDs.

Examples found in repository?
examples/diamond_flow.rs (line 50)
24fn main() {
25    // Create a diamond graph
26    let graph = create_diamond_graph();
27    println!("Created diamond graph: A -> B,C -> D");
28    println!("D requires inputs from BOTH B and C\n");
29
30    let mut net = Net::new(graph);
31
32    // Create two packets and place them on edges from A
33    let packet1 = create_packet(&mut net);
34    let packet2 = create_packet(&mut net);
35    println!("Created packets: {} and {}", packet1, packet2);
36
37    // Place packet1 on edge A -> B
38    let edge_a_b = edge_location("A", "out1", "B", "in");
39    net.do_action(&NetAction::TransportPacketToLocation(packet1.clone(), edge_a_b));
40    println!("Placed packet1 on edge A -> B");
41
42    // Place packet2 on edge A -> C
43    let edge_a_c = edge_location("A", "out2", "C", "in");
44    net.do_action(&NetAction::TransportPacketToLocation(packet2.clone(), edge_a_c));
45    println!("Placed packet2 on edge A -> C");
46
47    // Run network - packets move to B and C, triggering epochs
48    net.do_action(&NetAction::RunNetUntilBlocked);
49
50    let startable = net.get_startable_epochs();
51    println!("\nAfter first run: {} startable epochs (B and C)", startable.len());
52
53    // Process B and C, sending outputs to D
54    for epoch_id in startable {
55        let epoch = net.get_epoch(&epoch_id).unwrap();
56        let node_name = epoch.node_name.clone();
57        println!("\nProcessing node {}", node_name);
58
59        // Start the epoch
60        let started = match net.do_action(&NetAction::StartEpoch(epoch_id.clone())) {
61            NetActionResponse::Success(NetActionResponseData::StartedEpoch(e), _) => e,
62            _ => panic!("Failed to start epoch"),
63        };
64
65        // Find and consume the input packet
66        let input_packet = started.in_salvo.packets[0].1.clone();
67        net.do_action(&NetAction::ConsumePacket(input_packet));
68
69        // Create output packet
70        let output = create_packet_in_epoch(&mut net, &started.id);
71
72        // Load into output port and send
73        net.do_action(&NetAction::LoadPacketIntoOutputPort(output, "out".to_string()));
74        net.do_action(&NetAction::SendOutputSalvo(started.id.clone(), "default".to_string()));
75
76        // Finish epoch
77        net.do_action(&NetAction::FinishEpoch(started.id));
78        println!("  Finished {} - sent packet to D", node_name);
79    }
80
81    // Run network - packets move from B->D and C->D edges to D's input ports
82    net.do_action(&NetAction::RunNetUntilBlocked);
83
84    // Check D's input ports
85    let d_in1 = PacketLocation::InputPort("D".to_string(), "in1".to_string());
86    let d_in2 = PacketLocation::InputPort("D".to_string(), "in2".to_string());
87    println!("\nD's input ports:");
88    println!("  in1 (from B): {} packets", net.packet_count_at(&d_in1));
89    println!("  in2 (from C): {} packets", net.packet_count_at(&d_in2));
90
91    // D should now have a startable epoch (both inputs present)
92    let startable_d = net.get_startable_epochs();
93    println!("\nStartable epochs at D: {}", startable_d.len());
94
95    if let Some(d_epoch_id) = startable_d.first() {
96        let d_epoch = net.get_epoch(d_epoch_id).unwrap();
97        println!("D's epoch received {} packets from both branches!", d_epoch.in_salvo.packets.len());
98    }
99
100    println!("\nDiamond flow example complete!");
101}
More examples
Hide additional examples
examples/linear_flow.rs (line 57)
19fn main() {
20    // Create a linear graph: A -> B -> C
21    let graph = create_linear_graph();
22    println!("Created graph with {} nodes", graph.nodes().len());
23
24    // Create a network from the graph
25    let mut net = Net::new(graph);
26
27    // Create a packet outside the network
28    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    // Transport packet to the edge A -> B
37    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    // Run the network - packet moves to B's input port and triggers an epoch
53    net.do_action(&NetAction::RunNetUntilBlocked);
54    println!("Ran network until blocked");
55
56    // Check for startable epochs
57    let startable = net.get_startable_epochs();
58    println!("Startable epochs: {}", startable.len());
59
60    if let Some(epoch_id) = startable.first() {
61        // Start the epoch
62        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                // In a real scenario, external code would process the packet here
67                // For this example, we'll just consume it and create an output
68
69                // Consume the input packet
70                net.do_action(&NetAction::ConsumePacket(packet_id));
71                println!("Consumed input packet");
72
73                // Create an output packet
74                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                // Load it into the output port
81                net.do_action(&NetAction::LoadPacketIntoOutputPort(output_packet.clone(), "out".to_string()));
82                println!("Loaded packet into output port");
83
84                // Send the output salvo
85                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                // Finish the epoch
89                net.do_action(&NetAction::FinishEpoch(epoch.id));
90                println!("Finished epoch");
91
92                // Run the network again - packet moves to C
93                net.do_action(&NetAction::RunNetUntilBlocked);
94                println!("Ran network until blocked again");
95
96                // Check for new startable epochs at C
97                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}
Source

pub fn get_packet(&self, packet_id: &PacketID) -> Option<&Packet>

Get a packet by ID.

Trait Implementations§

Source§

impl Debug for Net

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Net

§

impl RefUnwindSafe for Net

§

impl Send for Net

§

impl Sync for Net

§

impl Unpin for Net

§

impl UnwindSafe for Net

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V