Skip to main content

Port

Struct Port 

Source
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_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. None for 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: PortId

Port identifier

§name: String

Port name

§direction: PortDirection

Port 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: bool

Whether 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,

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>

Get a reference to the buffer

Source

pub fn buffer_mut(&mut self) -> &mut FixedBuffer<T, BUF_SIZE>

Get a mutable reference to the buffer

Source

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.

Source

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.

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

Source

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.

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> ActivePort<T, BUF_SIZE> for Port<T, BUF_SIZE>
where T: Transcendental,

Source§

fn pull(&mut self) -> Option<[T; BUF_SIZE]>

Pull data from the port (for input ports).
Source§

fn push(&mut self, data: [T; BUF_SIZE]) -> Result<(), PortError>

Push data into the port (for output ports).
Source§

fn is_connected(&self) -> bool

Check if the port is connected.
Source§

fn on_tick(&mut self, _tick: &ClockTick)

Called on each clock tick (optional).
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> Freeze for Port<T, BUF_SIZE>
where T: Freeze,

§

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

§

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,

§

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

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