pub struct Port<T, const BUF_SIZE: usize>where
T: Transcendental,{
pub id: PortId,
pub name: String,
pub direction: PortDirection,
/* private fields */
}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 on exclusive 1:1 edges only.Nonefor fan-in, fan-out, and feedback ports (each materializes an independent copy).
§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)
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>
Low-level access to the port’s own buffer (engine / I-O boundary).
Nodes should prefer read: for a signal input this
returns the port’s own buffer, which is not the effective input on a
zero-copy edge.
Sourcepub fn read(&self) -> &[T; BUF_SIZE]
pub fn read(&self) -> &[T; BUF_SIZE]
Read the effective input block for this port (zero-copy aware).
On an exclusive 1:1 edge this is the upstream output buffer; otherwise it is the port’s own (materialized) buffer. This is the correct way for a node to read a signal input.
Sourcepub fn write(&mut self) -> &mut [T; BUF_SIZE]
pub fn write(&mut self) -> &mut [T; BUF_SIZE]
Mutable access to this port’s output block. The canonical way for a node to write its output samples.
Sourcepub fn write_from(&mut self, src: &[T; BUF_SIZE])
pub fn write_from(&mut self, src: &[T; BUF_SIZE])
Write this port’s output block from a source array.
Sourcepub fn feedback(&self) -> Option<&[T; BUF_SIZE]>
pub fn feedback(&self) -> Option<&[T; BUF_SIZE]>
The delayed feedback block, if this port is on a feedback edge.
Sourcepub fn data_received(&self) -> bool
pub fn data_received(&self) -> bool
Whether this input port received fresh data in the current graph cycle.
Sourcepub fn set_data_received(&mut self, value: bool)
pub fn set_data_received(&mut self, value: bool)
Set the data_received flag (sinks reset it after consuming).
Sourcepub fn downstream(&self) -> &[(usize, usize)]
pub fn downstream(&self) -> &[(usize, usize)]
Downstream signal connections (target_node, target_port) (serialization).
Sourcepub fn feedback_downstream(&self) -> &[(usize, usize)]
pub fn feedback_downstream(&self) -> &[(usize, usize)]
Feedback edge targets from this output port (serialization).
Sourcepub fn downstream_input_ptrs(&self) -> &[*mut Port<T, BUF_SIZE>]
pub fn downstream_input_ptrs(&self) -> &[*mut Port<T, BUF_SIZE>]
Direct pointers to downstream input ports (engine propagation).
Sourcepub fn downstream_nodes(&self) -> &[*mut NodeVariant<T, BUF_SIZE>]
pub fn downstream_nodes(&self) -> &[*mut NodeVariant<T, BUF_SIZE>]
Unique downstream nodes fed by this output port (engine propagation).
Sourcepub fn upstream_node(&self) -> *mut NodeVariant<T, BUF_SIZE>
pub fn upstream_node(&self) -> *mut NodeVariant<T, BUF_SIZE>
The upstream node feeding this input port (pull model), or null.
Sourcepub fn has_upstream_buffer(&self) -> bool
pub fn has_upstream_buffer(&self) -> bool
Whether this input port aliases an upstream buffer (exclusive 1:1 edge).
Sourcepub fn add_downstream(&mut self, target_node: usize, target_port: usize)
pub fn add_downstream(&mut self, target_node: usize, target_port: usize)
Record a downstream signal connection (target_node, target_port).
Sourcepub fn add_feedback_downstream(
&mut self,
target_node: usize,
target_port: usize,
)
pub fn add_feedback_downstream( &mut self, target_node: usize, target_port: usize, )
Record a feedback edge target (target_node, target_port).
Sourcepub fn add_downstream_input_ptr(&mut self, ptr: *mut Port<T, BUF_SIZE>)
pub fn add_downstream_input_ptr(&mut self, ptr: *mut Port<T, BUF_SIZE>)
Append a direct pointer to a downstream input port.
Sourcepub fn add_downstream_node(&mut self, node: *mut NodeVariant<T, BUF_SIZE>)
pub fn add_downstream_node(&mut self, node: *mut NodeVariant<T, BUF_SIZE>)
Append a downstream node pointer, deduplicating on identity.
Sourcepub fn set_upstream_node(&mut self, node: *mut NodeVariant<T, BUF_SIZE>)
pub fn set_upstream_node(&mut self, node: *mut NodeVariant<T, BUF_SIZE>)
Set the pull-model upstream node pointer.
Sourcepub fn set_upstream_buffer(
&mut self,
buffer: Option<*const FixedBuffer<T, BUF_SIZE>>,
)
pub fn set_upstream_buffer( &mut self, buffer: Option<*const FixedBuffer<T, BUF_SIZE>>, )
Set the zero-copy upstream buffer alias (exclusive 1:1 edges only).
Sourcepub fn init_feedback_buffer(&mut self)
pub fn init_feedback_buffer(&mut self)
Allocate this port’s feedback buffer (feedback edge endpoint).
Sourcepub fn feedback_buffer_ptr(&self) -> *mut Option<FixedBuffer<T, BUF_SIZE>>
pub fn feedback_buffer_ptr(&self) -> *mut Option<FixedBuffer<T, BUF_SIZE>>
Raw pointer to this port’s feedback_buffer, for wiring feedback_ptrs.
Sourcepub fn add_feedback_ptr(&mut self, ptr: *mut Option<FixedBuffer<T, BUF_SIZE>>)
pub fn add_feedback_ptr(&mut self, ptr: *mut Option<FixedBuffer<T, BUF_SIZE>>)
Append a pointer to a downstream input port’s feedback buffer.
Sourcepub fn is_zero_copy(&self) -> bool
pub fn is_zero_copy(&self) -> bool
Whether this input port is a pure zero-copy passthrough.
True when it aliases a single upstream output buffer
(upstream_buffer is set) and performs no per-port processing —
no action, no pending_command, and no feedback mixing. Such a
port is never materialized into its own buffer: the consumer reads
the upstream buffer directly through signal_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 a zero-copy input port returns the upstream output buffer directly.
Otherwise returns the local buffer (materialized by run_action /
feedback pre_process).
Sourcepub fn pre_process(&mut self)
pub fn pre_process(&mut self)
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,
ctx: &RenderContext,
tick: &ClockTick,
) -> Result<(), ProcessError>
pub fn propagate( &self, ctx: &RenderContext, tick: &ClockTick, ) -> Result<(), ProcessError>
Propagate this port’s own buffer to all downstream input ports.
For each downstream input port that is not a zero-copy passthrough
(fan-in, feedback, or a port with its own action/pending_command),
materialize the data into that port’s buffer via run_action.
Zero-copy passthrough ports are left untouched — their consumer reads
this output buffer directly through signal_buffer,
so no copy is performed. Then process each 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]>,
) -> Result<(), ProcessError>
pub fn run_action( &mut self, input: Option<&[T; BUF_SIZE]>, ) -> 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.