pub struct Port<T, const BUF_SIZE: usize>where
T: Transcendental,{Show 15 fields
pub id: PortId,
pub name: String,
pub direction: PortDirection,
pub action: Option<Box<dyn Algorithm<T>>>,
pub pending_command: Option<T>,
pub buffer: FixedBuffer<T, BUF_SIZE>,
pub feedback_buffer: Option<FixedBuffer<T, BUF_SIZE>>,
pub downstream: Vec<(usize, usize)>,
pub downstream_input_ptrs: Vec<*mut Port<T, BUF_SIZE>>,
pub downstream_nodes: Vec<*mut NodeVariant<T, BUF_SIZE>>,
pub parent: *mut NodeVariant<T, BUF_SIZE>,
pub upstream_buffer: Option<*const FixedBuffer<T, BUF_SIZE>>,
pub feedback_downstream: Vec<(usize, usize)>,
pub feedback_ptrs: Vec<*mut Option<FixedBuffer<T, BUF_SIZE>>>,
pub data_received: bool,
}Expand description
A port on a node.
Each port has an owned FixedBuffer<T, BUF_SIZE> for its data and an optional
Action that defines per-port processing. Output ports typically have
an action; input ports may have one for preprocessing.
Ports can optionally participate in feedback edges:
- On an output port in a feedback edge,
feedback_bufferstores the previous block’s output, snapshotted after DSP viasnapshot_feedback(). - On an input port in a feedback edge,
feedback_bufferholds the delayed feedback value that gets mixed intobufferbypre_process(). downstreamlists signal connections from this output port to input ports of other nodes, populated at build time by the graph builder.upstream_bufferon input ports: direct pointer to the upstream output port’s buffer for zero-copy routing.Nonefor fan-in/feedback ports.
§Safety
upstream_buffer is safe because the graph topology is immutable and
processing is strictly single-threaded in topological order. The
upstream output buffer is guaranteed to outlive the downstream input
port that references it.
Fields§
§id: PortIdPort identifier
name: StringPort name
direction: PortDirectionPort direction (input/output)
action: Option<Box<dyn Algorithm<T>>>Per-port processing algorithm (None for simple input ports)
pending_command: Option<T>Pending command value from the control path
buffer: FixedBuffer<T, BUF_SIZE>Owned signal buffer (for output ports and input ports without upstream)
feedback_buffer: Option<FixedBuffer<T, BUF_SIZE>>Delayed feedback state (None if not on a feedback edge)
downstream: Vec<(usize, usize)>Downstream signal connections: (target_node_index, target_port_index).
Used for serialization and by GraphBuilder::build().
downstream_input_ptrs: Vec<*mut Port<T, BUF_SIZE>>Direct pointers to downstream input ports. Filled by
GraphBuilder::build(). Used by propagate to copy data.
downstream_nodes: Vec<*mut NodeVariant<T, BUF_SIZE>>Unique downstream nodes (one per target, deduplicated at build time).
Filled by GraphBuilder::build(). Used by propagate to recurse
into downstream nodes — no runtime deduplication needed.
parent: *mut NodeVariant<T, BUF_SIZE>Pointer to the NodeVariant that
owns this port. Set after graph construction. Enables recursive
signal propagation without a nodes slice.
upstream_buffer: Option<*const FixedBuffer<T, BUF_SIZE>>Direct pointer to upstream output buffer for zero-copy routing.
Some for input ports in 1:1 or fan-out connections (first upstream).
None for output ports, fan-in (second+ upstream), or unconnected.
Valid for the engine’s lifetime.
feedback_downstream: Vec<(usize, usize)>Feedback edge targets from this output port (for serialization)
feedback_ptrs: Vec<*mut Option<FixedBuffer<T, BUF_SIZE>>>Direct pointers to feedback_buffer on downstream input ports.
Set by GraphBuilder::build() for feedback edges.
snapshot_feedback() copies its buffer into each target.
data_received: boolWhether this input port has received new data in the current graph cycle.
Set by propagate when a downstream input port receives a buffer copy.
Consumer nodes (esp. Sinks) check this flag to decide whether all
input channels are fresh before producing output.
Implementations§
Source§impl<T, const BUF_SIZE: usize> Port<T, BUF_SIZE>where
T: Transcendental,
impl<T, const BUF_SIZE: usize> Port<T, BUF_SIZE>where
T: Transcendental,
Sourcepub fn output(node_id: NodeId, index: u16, name: &str) -> Port<T, BUF_SIZE>
pub fn output(node_id: NodeId, index: u16, name: &str) -> Port<T, BUF_SIZE>
Create a new signal output port
Sourcepub fn input(node_id: NodeId, index: u16, name: &str) -> Port<T, BUF_SIZE>
pub fn input(node_id: NodeId, index: u16, name: &str) -> Port<T, BUF_SIZE>
Create a new signal input port
Sourcepub fn control_output(
node_id: NodeId,
index: u16,
name: &str,
) -> Port<T, BUF_SIZE>
pub fn control_output( node_id: NodeId, index: u16, name: &str, ) -> Port<T, BUF_SIZE>
Create a new control output port
Sourcepub fn control_output_with_action(
node_id: NodeId,
index: u16,
name: &str,
action: Box<dyn Algorithm<T>>,
) -> Port<T, BUF_SIZE>
pub fn control_output_with_action( node_id: NodeId, index: u16, name: &str, action: Box<dyn Algorithm<T>>, ) -> Port<T, BUF_SIZE>
Create a new control output port with an algorithm
Sourcepub fn control_input(
node_id: NodeId,
index: u16,
name: &str,
) -> Port<T, BUF_SIZE>
pub fn control_input( node_id: NodeId, index: u16, name: &str, ) -> Port<T, BUF_SIZE>
Create a new control input port
Sourcepub fn buffer(&self) -> &FixedBuffer<T, BUF_SIZE>
pub fn buffer(&self) -> &FixedBuffer<T, BUF_SIZE>
Get a reference to the buffer
Sourcepub fn buffer_mut(&mut self) -> &mut FixedBuffer<T, BUF_SIZE>
pub fn buffer_mut(&mut self) -> &mut FixedBuffer<T, BUF_SIZE>
Get a mutable reference to the buffer
Sourcepub fn signal_buffer(&self) -> &FixedBuffer<T, BUF_SIZE>
pub fn signal_buffer(&self) -> &FixedBuffer<T, BUF_SIZE>
Get the effective signal buffer for this port.
For zero-copy input ports returns the upstream output buffer. For output ports and copy-based input ports returns the local buffer.
Sourcepub fn pre_process(&mut self, _tick: &ClockTick)
pub fn pre_process(&mut self, _tick: &ClockTick)
Pre-process this port before node DSP.
For input ports on a feedback edge, mixes the delayed feedback
(from feedback_buffer) into the current buffer.
Sourcepub fn snapshot_feedback(&mut self)
pub fn snapshot_feedback(&mut self)
Snapshot the buffer into feedback_buffer and propagate to
downstream input ports via feedback_ptrs.
For output ports on a feedback edge, saves the current buffer
so it can be used as delayed feedback in the next block, then
copies it into each target input port’s feedback_buffer.
No-op when feedback_buffer is None.
Sourcepub fn propagate(
&self,
buffer: &FixedBuffer<T, BUF_SIZE>,
ctx: &ActionContext<'_>,
) -> Result<(), ProcessError>
pub fn propagate( &self, buffer: &FixedBuffer<T, BUF_SIZE>, ctx: &ActionContext<'_>, ) -> Result<(), ProcessError>
Propagate this port’s buffer to all downstream input ports.
Iterates over downstream and copies buffer into each target
input port’s buffer. The caller must ensure no aliasing between
this port’s node and any target node (guaranteed by DAG topology).
tick is the current clock tick, available for future
sample-accurate or time-varying port-level propagation.
Copy buffer into every downstream input port (unless zero-copy),
run each port’s algorithm, then process the downstream node and
recurse through its output ports.
No heap allocations — downstream_nodes is pre‑filled at build time.
Sourcepub fn run_action(
&mut self,
input: Option<&[T; BUF_SIZE]>,
ctx: &ActionContext<'_>,
) -> Result<(), ProcessError>
pub fn run_action( &mut self, input: Option<&[T; BUF_SIZE]>, ctx: &ActionContext<'_>, ) -> Result<(), ProcessError>
Run the port’s algorithm.
Delivers any pending command via Algorithm::apply_command(), then
calls Algorithm::process() with the input and output slices.
When no algorithm is attached, the pending command value (if any)
is written directly into the buffer; otherwise input is passed
through or zero-filled.