Skip to main content

Port

Struct Port 

Source
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_buffer stores the previous block’s output, snapshotted after DSP via snapshot_feedback().
  • On an input port in a feedback edge, feedback_buffer holds the delayed feedback value that gets mixed into buffer by pre_process().
  • downstream lists signal connections from this output port to input ports of other nodes, populated at build time by the graph builder.
  • upstream_buffer on input ports: direct pointer to the upstream output port’s buffer for zero-copy routing on exclusive 1:1 edges only. None for 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: PortId

Port identifier

§name: String

Port name

§direction: PortDirection

Port direction (input/output)

Implementations§

Source§

impl<T, const BUF_SIZE: usize> Port<T, BUF_SIZE>
where T: Transcendental,

Source

pub fn output(node_id: NodeId, index: u16, name: &str) -> Port<T, BUF_SIZE>

Create a new signal output port

Source

pub fn input(node_id: NodeId, index: u16, name: &str) -> Port<T, BUF_SIZE>

Create a new signal input port

Source

pub fn control_output( node_id: NodeId, index: u16, name: &str, ) -> Port<T, BUF_SIZE>

Create a new control output port

Source

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

Source

pub fn control_input( node_id: NodeId, index: u16, name: &str, ) -> Port<T, BUF_SIZE>

Create a new control input port

Source

pub fn id(&self) -> PortId

Get the port ID

Source

pub fn name(&self) -> &str

Get the port name

Source

pub fn is_input(&self) -> bool

Check if port is an input

Source

pub fn is_output(&self) -> bool

Check if port is an output

Source

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.

Source

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.

Source

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.

Source

pub fn write_from(&mut self, src: &[T; BUF_SIZE])

Write this port’s output block from a source array.

Source

pub fn feedback(&self) -> Option<&[T; BUF_SIZE]>

The delayed feedback block, if this port is on a feedback edge.

Source

pub fn data_received(&self) -> bool

Whether this input port received fresh data in the current graph cycle.

Source

pub fn set_data_received(&mut self, value: bool)

Set the data_received flag (sinks reset it after consuming).

Source

pub fn downstream(&self) -> &[(usize, usize)]

Downstream signal connections (target_node, target_port) (serialization).

Source

pub fn feedback_downstream(&self) -> &[(usize, usize)]

Feedback edge targets from this output port (serialization).

Source

pub fn downstream_input_ptrs(&self) -> &[*mut Port<T, BUF_SIZE>]

Direct pointers to downstream input ports (engine propagation).

Source

pub fn downstream_nodes(&self) -> &[*mut NodeVariant<T, BUF_SIZE>]

Unique downstream nodes fed by this output port (engine propagation).

Source

pub fn upstream_node(&self) -> *mut NodeVariant<T, BUF_SIZE>

The upstream node feeding this input port (pull model), or null.

Source

pub fn has_upstream_buffer(&self) -> bool

Whether this input port aliases an upstream buffer (exclusive 1:1 edge).

Source

pub fn add_downstream(&mut self, target_node: usize, target_port: usize)

Record a downstream signal connection (target_node, target_port).

Source

pub fn add_feedback_downstream( &mut self, target_node: usize, target_port: usize, )

Record a feedback edge target (target_node, target_port).

Source

pub fn add_downstream_input_ptr(&mut self, ptr: *mut Port<T, BUF_SIZE>)

Append a direct pointer to a downstream input port.

Source

pub fn add_downstream_node(&mut self, node: *mut NodeVariant<T, BUF_SIZE>)

Append a downstream node pointer, deduplicating on identity.

Source

pub fn set_upstream_node(&mut self, node: *mut NodeVariant<T, BUF_SIZE>)

Set the pull-model upstream node pointer.

Source

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).

Source

pub fn init_feedback_buffer(&mut self)

Allocate this port’s feedback buffer (feedback edge endpoint).

Source

pub fn feedback_buffer_ptr(&self) -> *mut Option<FixedBuffer<T, BUF_SIZE>>

Raw pointer to this port’s feedback_buffer, for wiring feedback_ptrs.

Source

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.

Source

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.

Source

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).

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn set_value(&mut self, value: T)

Set a command value for this port.

The value is stored as a pending command and delivered to the algorithm (or written directly to the buffer) on the next run_action() call.

Trait Implementations§

Source§

impl<T, const BUF_SIZE: usize> Debug for Port<T, BUF_SIZE>
where T: Transcendental,

Source§

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

Formats the value using the given formatter. Read more
Source§

impl<T, const BUF_SIZE: usize> Send for Port<T, BUF_SIZE>
where T: Transcendental + Send,

Source§

impl<T, const BUF_SIZE: usize> Sync for Port<T, BUF_SIZE>
where T: Transcendental + Sync,

Auto Trait Implementations§

§

impl<T, const BUF_SIZE: usize> !RefUnwindSafe for Port<T, BUF_SIZE>

§

impl<T, const BUF_SIZE: usize> !UnwindSafe for Port<T, BUF_SIZE>

§

impl<T, const BUF_SIZE: usize> Freeze for Port<T, BUF_SIZE>
where T: Freeze,

§

impl<T, const BUF_SIZE: usize> Unpin for Port<T, BUF_SIZE>
where T: Unpin,

§

impl<T, const BUF_SIZE: usize> UnsafeUnpin for Port<T, BUF_SIZE>
where T: UnsafeUnpin,

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> AsAny for T
where T: 'static,

Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert to &dyn std::any::Any
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert to &mut dyn std::any::Any
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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

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